/******/ (function(modules) { // webpackBootstrap
/******/ 	// The module cache
/******/ 	var installedModules = {};

/******/ 	// The require function
/******/ 	function __webpack_require__(moduleId) {

/******/ 		// Check if module is in cache
/******/ 		if(installedModules[moduleId])
/******/ 			return installedModules[moduleId].exports;

/******/ 		// Create a new module (and put it into the cache)
/******/ 		var module = installedModules[moduleId] = {
/******/ 			exports: {},
/******/ 			id: moduleId,
/******/ 			loaded: false
/******/ 		};

/******/ 		// Execute the module function
/******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);

/******/ 		// Flag the module as loaded
/******/ 		module.loaded = true;

/******/ 		// Return the exports of the module
/******/ 		return module.exports;
/******/ 	}


/******/ 	// expose the modules object (__webpack_modules__)
/******/ 	__webpack_require__.m = modules;

/******/ 	// expose the module cache
/******/ 	__webpack_require__.c = installedModules;

/******/ 	// __webpack_public_path__
/******/ 	__webpack_require__.p = "";

/******/ 	// Load entry module and return exports
/******/ 	return __webpack_require__(0);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ function(module, exports, __webpack_require__) {

	__webpack_require__(1);
	__webpack_require__(2);
	__webpack_require__(3);
	__webpack_require__(7);
	__webpack_require__(8);
	module.exports = __webpack_require__(9);


/***/ },
/* 1 */
/***/ function(module, exports, __webpack_require__) {

	var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [], __WEBPACK_AMD_DEFINE_RESULT__ = function() {
	  // A placeholder for MailPoet object
	  var MailPoet = {};

	  // Expose MailPoet globally
	  window.MailPoet = MailPoet;

	  return MailPoet;
	}.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));


/***/ },
/* 2 */
/***/ function(module, exports, __webpack_require__) {

	var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
	    __webpack_require__(1)
	  ], __WEBPACK_AMD_DEFINE_RESULT__ = function(
	    mp
	) {
	  'use strict';
	  var MailPoet = mp;

	  var translations = {};

	  MailPoet.I18n = {
	    add: function(key, value) {
	      translations[key] = value;
	    },
	    t: function(key) {
	      return translations[key] || 'TRANSLATION "%$1s" NOT FOUND'.replace("%$1s", key);
	    },
	    all: function() {
	      return translations;
	    }
	  };

	}.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));


/***/ },
/* 3 */
/***/ function(module, exports, __webpack_require__) {

	var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;function requestFailed(errorMessage, xhr) {
	  if (xhr.responseJSON) {
	    return xhr.responseJSON;
	  }
	  var message = errorMessage.replace("%d", xhr.status);
	  return {
	    errors: [
	      {
	        message: message
	      }
	    ]
	  };
	}

	!(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(1), __webpack_require__(4), __webpack_require__(5)], __WEBPACK_AMD_DEFINE_RESULT__ = function(mp, jQuery, _) {
	  var MailPoet = mp;

	  MailPoet.Ajax = {
	      version: 0.5,
	      options: {},
	      defaults: {
	        url: null,
	        api_version: null,
	        endpoint: null,
	        action: null,
	        token: null,
	        data: {}
	      },
	      post: function(options) {
	        return this.request('post', options);
	      },
	      init: function(options) {
	        // merge options
	        this.options = jQuery.extend({}, this.defaults, options);

	        // set default url
	        if(this.options.url === null) {
	          this.options.url = ajaxurl;
	        }

	        // set default token
	        if(this.options.token === null) {
	          this.options.token = window.mailpoet_token;
	        }
	      },
	      getParams: function() {
	        return {
	          action: 'mailpoet',
	          api_version: this.options.api_version,
	          token: this.options.token,
	          endpoint: this.options.endpoint,
	          method: this.options.action,
	          data: this.options.data || {}
	        };
	      },
	      request: function(method, options) {
	        // set options
	        this.init(options);

	        // set request params
	        var params = this.getParams();

	        // remove null values from the data object
	        if (_.isObject(params.data)) {
	          params.data = _.pick(params.data, function(value) {
	            return (value !== null);
	          });
	        }

	        // ajax request
	        var deferred = jQuery.post(
	          this.options.url,
	          params,
	          null,
	          'json'
	        ).then(function(data) {
	          return data;
	        }, _.partial(requestFailed, MailPoet.I18n.t('ajaxFailedErrorMessage')));

	        // clear options
	        this.options = {};

	        return deferred;
	      }
	  };
	}.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));


/***/ },
/* 4 */
/***/ function(module, exports) {

	module.exports = jQuery;

/***/ },
/* 5 */
/***/ function(module, exports, __webpack_require__) {

	/* WEBPACK VAR INJECTION */(function(global) {module.exports = global["_"] = __webpack_require__(6);
	/* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }())))

/***/ },
/* 6 */
/***/ function(module, exports, __webpack_require__) {

	var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;//     Underscore.js 1.8.3
	//     http://underscorejs.org
	//     (c) 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
	//     Underscore may be freely distributed under the MIT license.

	(function() {

	  // Baseline setup
	  // --------------

	  // Establish the root object, `window` in the browser, or `exports` on the server.
	  var root = this;

	  // Save the previous value of the `_` variable.
	  var previousUnderscore = root._;

	  // Save bytes in the minified (but not gzipped) version:
	  var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype;

	  // Create quick reference variables for speed access to core prototypes.
	  var
	    push             = ArrayProto.push,
	    slice            = ArrayProto.slice,
	    toString         = ObjProto.toString,
	    hasOwnProperty   = ObjProto.hasOwnProperty;

	  // All **ECMAScript 5** native function implementations that we hope to use
	  // are declared here.
	  var
	    nativeIsArray      = Array.isArray,
	    nativeKeys         = Object.keys,
	    nativeBind         = FuncProto.bind,
	    nativeCreate       = Object.create;

	  // Naked function reference for surrogate-prototype-swapping.
	  var Ctor = function(){};

	  // Create a safe reference to the Underscore object for use below.
	  var _ = function(obj) {
	    if (obj instanceof _) return obj;
	    if (!(this instanceof _)) return new _(obj);
	    this._wrapped = obj;
	  };

	  // Export the Underscore object for **Node.js**, with
	  // backwards-compatibility for the old `require()` API. If we're in
	  // the browser, add `_` as a global object.
	  if (true) {
	    if (typeof module !== 'undefined' && module.exports) {
	      exports = module.exports = _;
	    }
	    exports._ = _;
	  } else {
	    root._ = _;
	  }

	  // Current version.
	  _.VERSION = '1.8.3';

	  // Internal function that returns an efficient (for current engines) version
	  // of the passed-in callback, to be repeatedly applied in other Underscore
	  // functions.
	  var optimizeCb = function(func, context, argCount) {
	    if (context === void 0) return func;
	    switch (argCount == null ? 3 : argCount) {
	      case 1: return function(value) {
	        return func.call(context, value);
	      };
	      case 2: return function(value, other) {
	        return func.call(context, value, other);
	      };
	      case 3: return function(value, index, collection) {
	        return func.call(context, value, index, collection);
	      };
	      case 4: return function(accumulator, value, index, collection) {
	        return func.call(context, accumulator, value, index, collection);
	      };
	    }
	    return function() {
	      return func.apply(context, arguments);
	    };
	  };

	  // A mostly-internal function to generate callbacks that can be applied
	  // to each element in a collection, returning the desired result — either
	  // identity, an arbitrary callback, a property matcher, or a property accessor.
	  var cb = function(value, context, argCount) {
	    if (value == null) return _.identity;
	    if (_.isFunction(value)) return optimizeCb(value, context, argCount);
	    if (_.isObject(value)) return _.matcher(value);
	    return _.property(value);
	  };
	  _.iteratee = function(value, context) {
	    return cb(value, context, Infinity);
	  };

	  // An internal function for creating assigner functions.
	  var createAssigner = function(keysFunc, undefinedOnly) {
	    return function(obj) {
	      var length = arguments.length;
	      if (length < 2 || obj == null) return obj;
	      for (var index = 1; index < length; index++) {
	        var source = arguments[index],
	            keys = keysFunc(source),
	            l = keys.length;
	        for (var i = 0; i < l; i++) {
	          var key = keys[i];
	          if (!undefinedOnly || obj[key] === void 0) obj[key] = source[key];
	        }
	      }
	      return obj;
	    };
	  };

	  // An internal function for creating a new object that inherits from another.
	  var baseCreate = function(prototype) {
	    if (!_.isObject(prototype)) return {};
	    if (nativeCreate) return nativeCreate(prototype);
	    Ctor.prototype = prototype;
	    var result = new Ctor;
	    Ctor.prototype = null;
	    return result;
	  };

	  var property = function(key) {
	    return function(obj) {
	      return obj == null ? void 0 : obj[key];
	    };
	  };

	  // Helper for collection methods to determine whether a collection
	  // should be iterated as an array or as an object
	  // Related: http://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength
	  // Avoids a very nasty iOS 8 JIT bug on ARM-64. #2094
	  var MAX_ARRAY_INDEX = Math.pow(2, 53) - 1;
	  var getLength = property('length');
	  var isArrayLike = function(collection) {
	    var length = getLength(collection);
	    return typeof length == 'number' && length >= 0 && length <= MAX_ARRAY_INDEX;
	  };

	  // Collection Functions
	  // --------------------

	  // The cornerstone, an `each` implementation, aka `forEach`.
	  // Handles raw objects in addition to array-likes. Treats all
	  // sparse array-likes as if they were dense.
	  _.each = _.forEach = function(obj, iteratee, context) {
	    iteratee = optimizeCb(iteratee, context);
	    var i, length;
	    if (isArrayLike(obj)) {
	      for (i = 0, length = obj.length; i < length; i++) {
	        iteratee(obj[i], i, obj);
	      }
	    } else {
	      var keys = _.keys(obj);
	      for (i = 0, length = keys.length; i < length; i++) {
	        iteratee(obj[keys[i]], keys[i], obj);
	      }
	    }
	    return obj;
	  };

	  // Return the results of applying the iteratee to each element.
	  _.map = _.collect = function(obj, iteratee, context) {
	    iteratee = cb(iteratee, context);
	    var keys = !isArrayLike(obj) && _.keys(obj),
	        length = (keys || obj).length,
	        results = Array(length);
	    for (var index = 0; index < length; index++) {
	      var currentKey = keys ? keys[index] : index;
	      results[index] = iteratee(obj[currentKey], currentKey, obj);
	    }
	    return results;
	  };

	  // Create a reducing function iterating left or right.
	  function createReduce(dir) {
	    // Optimized iterator function as using arguments.length
	    // in the main function will deoptimize the, see #1991.
	    function iterator(obj, iteratee, memo, keys, index, length) {
	      for (; index >= 0 && index < length; index += dir) {
	        var currentKey = keys ? keys[index] : index;
	        memo = iteratee(memo, obj[currentKey], currentKey, obj);
	      }
	      return memo;
	    }

	    return function(obj, iteratee, memo, context) {
	      iteratee = optimizeCb(iteratee, context, 4);
	      var keys = !isArrayLike(obj) && _.keys(obj),
	          length = (keys || obj).length,
	          index = dir > 0 ? 0 : length - 1;
	      // Determine the initial value if none is provided.
	      if (arguments.length < 3) {
	        memo = obj[keys ? keys[index] : index];
	        index += dir;
	      }
	      return iterator(obj, iteratee, memo, keys, index, length);
	    };
	  }

	  // **Reduce** builds up a single result from a list of values, aka `inject`,
	  // or `foldl`.
	  _.reduce = _.foldl = _.inject = createReduce(1);

	  // The right-associative version of reduce, also known as `foldr`.
	  _.reduceRight = _.foldr = createReduce(-1);

	  // Return the first value which passes a truth test. Aliased as `detect`.
	  _.find = _.detect = function(obj, predicate, context) {
	    var key;
	    if (isArrayLike(obj)) {
	      key = _.findIndex(obj, predicate, context);
	    } else {
	      key = _.findKey(obj, predicate, context);
	    }
	    if (key !== void 0 && key !== -1) return obj[key];
	  };

	  // Return all the elements that pass a truth test.
	  // Aliased as `select`.
	  _.filter = _.select = function(obj, predicate, context) {
	    var results = [];
	    predicate = cb(predicate, context);
	    _.each(obj, function(value, index, list) {
	      if (predicate(value, index, list)) results.push(value);
	    });
	    return results;
	  };

	  // Return all the elements for which a truth test fails.
	  _.reject = function(obj, predicate, context) {
	    return _.filter(obj, _.negate(cb(predicate)), context);
	  };

	  // Determine whether all of the elements match a truth test.
	  // Aliased as `all`.
	  _.every = _.all = function(obj, predicate, context) {
	    predicate = cb(predicate, context);
	    var keys = !isArrayLike(obj) && _.keys(obj),
	        length = (keys || obj).length;
	    for (var index = 0; index < length; index++) {
	      var currentKey = keys ? keys[index] : index;
	      if (!predicate(obj[currentKey], currentKey, obj)) return false;
	    }
	    return true;
	  };

	  // Determine if at least one element in the object matches a truth test.
	  // Aliased as `any`.
	  _.some = _.any = function(obj, predicate, context) {
	    predicate = cb(predicate, context);
	    var keys = !isArrayLike(obj) && _.keys(obj),
	        length = (keys || obj).length;
	    for (var index = 0; index < length; index++) {
	      var currentKey = keys ? keys[index] : index;
	      if (predicate(obj[currentKey], currentKey, obj)) return true;
	    }
	    return false;
	  };

	  // Determine if the array or object contains a given item (using `===`).
	  // Aliased as `includes` and `include`.
	  _.contains = _.includes = _.include = function(obj, item, fromIndex, guard) {
	    if (!isArrayLike(obj)) obj = _.values(obj);
	    if (typeof fromIndex != 'number' || guard) fromIndex = 0;
	    return _.indexOf(obj, item, fromIndex) >= 0;
	  };

	  // Invoke a method (with arguments) on every item in a collection.
	  _.invoke = function(obj, method) {
	    var args = slice.call(arguments, 2);
	    var isFunc = _.isFunction(method);
	    return _.map(obj, function(value) {
	      var func = isFunc ? method : value[method];
	      return func == null ? func : func.apply(value, args);
	    });
	  };

	  // Convenience version of a common use case of `map`: fetching a property.
	  _.pluck = function(obj, key) {
	    return _.map(obj, _.property(key));
	  };

	  // Convenience version of a common use case of `filter`: selecting only objects
	  // containing specific `key:value` pairs.
	  _.where = function(obj, attrs) {
	    return _.filter(obj, _.matcher(attrs));
	  };

	  // Convenience version of a common use case of `find`: getting the first object
	  // containing specific `key:value` pairs.
	  _.findWhere = function(obj, attrs) {
	    return _.find(obj, _.matcher(attrs));
	  };

	  // Return the maximum element (or element-based computation).
	  _.max = function(obj, iteratee, context) {
	    var result = -Infinity, lastComputed = -Infinity,
	        value, computed;
	    if (iteratee == null && obj != null) {
	      obj = isArrayLike(obj) ? obj : _.values(obj);
	      for (var i = 0, length = obj.length; i < length; i++) {
	        value = obj[i];
	        if (value > result) {
	          result = value;
	        }
	      }
	    } else {
	      iteratee = cb(iteratee, context);
	      _.each(obj, function(value, index, list) {
	        computed = iteratee(value, index, list);
	        if (computed > lastComputed || computed === -Infinity && result === -Infinity) {
	          result = value;
	          lastComputed = computed;
	        }
	      });
	    }
	    return result;
	  };

	  // Return the minimum element (or element-based computation).
	  _.min = function(obj, iteratee, context) {
	    var result = Infinity, lastComputed = Infinity,
	        value, computed;
	    if (iteratee == null && obj != null) {
	      obj = isArrayLike(obj) ? obj : _.values(obj);
	      for (var i = 0, length = obj.length; i < length; i++) {
	        value = obj[i];
	        if (value < result) {
	          result = value;
	        }
	      }
	    } else {
	      iteratee = cb(iteratee, context);
	      _.each(obj, function(value, index, list) {
	        computed = iteratee(value, index, list);
	        if (computed < lastComputed || computed === Infinity && result === Infinity) {
	          result = value;
	          lastComputed = computed;
	        }
	      });
	    }
	    return result;
	  };

	  // Shuffle a collection, using the modern version of the
	  // [Fisher-Yates shuffle](http://en.wikipedia.org/wiki/Fisher–Yates_shuffle).
	  _.shuffle = function(obj) {
	    var set = isArrayLike(obj) ? obj : _.values(obj);
	    var length = set.length;
	    var shuffled = Array(length);
	    for (var index = 0, rand; index < length; index++) {
	      rand = _.random(0, index);
	      if (rand !== index) shuffled[index] = shuffled[rand];
	      shuffled[rand] = set[index];
	    }
	    return shuffled;
	  };

	  // Sample **n** random values from a collection.
	  // If **n** is not specified, returns a single random element.
	  // The internal `guard` argument allows it to work with `map`.
	  _.sample = function(obj, n, guard) {
	    if (n == null || guard) {
	      if (!isArrayLike(obj)) obj = _.values(obj);
	      return obj[_.random(obj.length - 1)];
	    }
	    return _.shuffle(obj).slice(0, Math.max(0, n));
	  };

	  // Sort the object's values by a criterion produced by an iteratee.
	  _.sortBy = function(obj, iteratee, context) {
	    iteratee = cb(iteratee, context);
	    return _.pluck(_.map(obj, function(value, index, list) {
	      return {
	        value: value,
	        index: index,
	        criteria: iteratee(value, index, list)
	      };
	    }).sort(function(left, right) {
	      var a = left.criteria;
	      var b = right.criteria;
	      if (a !== b) {
	        if (a > b || a === void 0) return 1;
	        if (a < b || b === void 0) return -1;
	      }
	      return left.index - right.index;
	    }), 'value');
	  };

	  // An internal function used for aggregate "group by" operations.
	  var group = function(behavior) {
	    return function(obj, iteratee, context) {
	      var result = {};
	      iteratee = cb(iteratee, context);
	      _.each(obj, function(value, index) {
	        var key = iteratee(value, index, obj);
	        behavior(result, value, key);
	      });
	      return result;
	    };
	  };

	  // Groups the object's values by a criterion. Pass either a string attribute
	  // to group by, or a function that returns the criterion.
	  _.groupBy = group(function(result, value, key) {
	    if (_.has(result, key)) result[key].push(value); else result[key] = [value];
	  });

	  // Indexes the object's values by a criterion, similar to `groupBy`, but for
	  // when you know that your index values will be unique.
	  _.indexBy = group(function(result, value, key) {
	    result[key] = value;
	  });

	  // Counts instances of an object that group by a certain criterion. Pass
	  // either a string attribute to count by, or a function that returns the
	  // criterion.
	  _.countBy = group(function(result, value, key) {
	    if (_.has(result, key)) result[key]++; else result[key] = 1;
	  });

	  // Safely create a real, live array from anything iterable.
	  _.toArray = function(obj) {
	    if (!obj) return [];
	    if (_.isArray(obj)) return slice.call(obj);
	    if (isArrayLike(obj)) return _.map(obj, _.identity);
	    return _.values(obj);
	  };

	  // Return the number of elements in an object.
	  _.size = function(obj) {
	    if (obj == null) return 0;
	    return isArrayLike(obj) ? obj.length : _.keys(obj).length;
	  };

	  // Split a collection into two arrays: one whose elements all satisfy the given
	  // predicate, and one whose elements all do not satisfy the predicate.
	  _.partition = function(obj, predicate, context) {
	    predicate = cb(predicate, context);
	    var pass = [], fail = [];
	    _.each(obj, function(value, key, obj) {
	      (predicate(value, key, obj) ? pass : fail).push(value);
	    });
	    return [pass, fail];
	  };

	  // Array Functions
	  // ---------------

	  // Get the first element of an array. Passing **n** will return the first N
	  // values in the array. Aliased as `head` and `take`. The **guard** check
	  // allows it to work with `_.map`.
	  _.first = _.head = _.take = function(array, n, guard) {
	    if (array == null) return void 0;
	    if (n == null || guard) return array[0];
	    return _.initial(array, array.length - n);
	  };

	  // Returns everything but the last entry of the array. Especially useful on
	  // the arguments object. Passing **n** will return all the values in
	  // the array, excluding the last N.
	  _.initial = function(array, n, guard) {
	    return slice.call(array, 0, Math.max(0, array.length - (n == null || guard ? 1 : n)));
	  };

	  // Get the last element of an array. Passing **n** will return the last N
	  // values in the array.
	  _.last = function(array, n, guard) {
	    if (array == null) return void 0;
	    if (n == null || guard) return array[array.length - 1];
	    return _.rest(array, Math.max(0, array.length - n));
	  };

	  // Returns everything but the first entry of the array. Aliased as `tail` and `drop`.
	  // Especially useful on the arguments object. Passing an **n** will return
	  // the rest N values in the array.
	  _.rest = _.tail = _.drop = function(array, n, guard) {
	    return slice.call(array, n == null || guard ? 1 : n);
	  };

	  // Trim out all falsy values from an array.
	  _.compact = function(array) {
	    return _.filter(array, _.identity);
	  };

	  // Internal implementation of a recursive `flatten` function.
	  var flatten = function(input, shallow, strict, startIndex) {
	    var output = [], idx = 0;
	    for (var i = startIndex || 0, length = getLength(input); i < length; i++) {
	      var value = input[i];
	      if (isArrayLike(value) && (_.isArray(value) || _.isArguments(value))) {
	        //flatten current level of array or arguments object
	        if (!shallow) value = flatten(value, shallow, strict);
	        var j = 0, len = value.length;
	        output.length += len;
	        while (j < len) {
	          output[idx++] = value[j++];
	        }
	      } else if (!strict) {
	        output[idx++] = value;
	      }
	    }
	    return output;
	  };

	  // Flatten out an array, either recursively (by default), or just one level.
	  _.flatten = function(array, shallow) {
	    return flatten(array, shallow, false);
	  };

	  // Return a version of the array that does not contain the specified value(s).
	  _.without = function(array) {
	    return _.difference(array, slice.call(arguments, 1));
	  };

	  // Produce a duplicate-free version of the array. If the array has already
	  // been sorted, you have the option of using a faster algorithm.
	  // Aliased as `unique`.
	  _.uniq = _.unique = function(array, isSorted, iteratee, context) {
	    if (!_.isBoolean(isSorted)) {
	      context = iteratee;
	      iteratee = isSorted;
	      isSorted = false;
	    }
	    if (iteratee != null) iteratee = cb(iteratee, context);
	    var result = [];
	    var seen = [];
	    for (var i = 0, length = getLength(array); i < length; i++) {
	      var value = array[i],
	          computed = iteratee ? iteratee(value, i, array) : value;
	      if (isSorted) {
	        if (!i || seen !== computed) result.push(value);
	        seen = computed;
	      } else if (iteratee) {
	        if (!_.contains(seen, computed)) {
	          seen.push(computed);
	          result.push(value);
	        }
	      } else if (!_.contains(result, value)) {
	        result.push(value);
	      }
	    }
	    return result;
	  };

	  // Produce an array that contains the union: each distinct element from all of
	  // the passed-in arrays.
	  _.union = function() {
	    return _.uniq(flatten(arguments, true, true));
	  };

	  // Produce an array that contains every item shared between all the
	  // passed-in arrays.
	  _.intersection = function(array) {
	    var result = [];
	    var argsLength = arguments.length;
	    for (var i = 0, length = getLength(array); i < length; i++) {
	      var item = array[i];
	      if (_.contains(result, item)) continue;
	      for (var j = 1; j < argsLength; j++) {
	        if (!_.contains(arguments[j], item)) break;
	      }
	      if (j === argsLength) result.push(item);
	    }
	    return result;
	  };

	  // Take the difference between one array and a number of other arrays.
	  // Only the elements present in just the first array will remain.
	  _.difference = function(array) {
	    var rest = flatten(arguments, true, true, 1);
	    return _.filter(array, function(value){
	      return !_.contains(rest, value);
	    });
	  };

	  // Zip together multiple lists into a single array -- elements that share
	  // an index go together.
	  _.zip = function() {
	    return _.unzip(arguments);
	  };

	  // Complement of _.zip. Unzip accepts an array of arrays and groups
	  // each array's elements on shared indices
	  _.unzip = function(array) {
	    var length = array && _.max(array, getLength).length || 0;
	    var result = Array(length);

	    for (var index = 0; index < length; index++) {
	      result[index] = _.pluck(array, index);
	    }
	    return result;
	  };

	  // Converts lists into objects. Pass either a single array of `[key, value]`
	  // pairs, or two parallel arrays of the same length -- one of keys, and one of
	  // the corresponding values.
	  _.object = function(list, values) {
	    var result = {};
	    for (var i = 0, length = getLength(list); i < length; i++) {
	      if (values) {
	        result[list[i]] = values[i];
	      } else {
	        result[list[i][0]] = list[i][1];
	      }
	    }
	    return result;
	  };

	  // Generator function to create the findIndex and findLastIndex functions
	  function createPredicateIndexFinder(dir) {
	    return function(array, predicate, context) {
	      predicate = cb(predicate, context);
	      var length = getLength(array);
	      var index = dir > 0 ? 0 : length - 1;
	      for (; index >= 0 && index < length; index += dir) {
	        if (predicate(array[index], index, array)) return index;
	      }
	      return -1;
	    };
	  }

	  // Returns the first index on an array-like that passes a predicate test
	  _.findIndex = createPredicateIndexFinder(1);
	  _.findLastIndex = createPredicateIndexFinder(-1);

	  // Use a comparator function to figure out the smallest index at which
	  // an object should be inserted so as to maintain order. Uses binary search.
	  _.sortedIndex = function(array, obj, iteratee, context) {
	    iteratee = cb(iteratee, context, 1);
	    var value = iteratee(obj);
	    var low = 0, high = getLength(array);
	    while (low < high) {
	      var mid = Math.floor((low + high) / 2);
	      if (iteratee(array[mid]) < value) low = mid + 1; else high = mid;
	    }
	    return low;
	  };

	  // Generator function to create the indexOf and lastIndexOf functions
	  function createIndexFinder(dir, predicateFind, sortedIndex) {
	    return function(array, item, idx) {
	      var i = 0, length = getLength(array);
	      if (typeof idx == 'number') {
	        if (dir > 0) {
	            i = idx >= 0 ? idx : Math.max(idx + length, i);
	        } else {
	            length = idx >= 0 ? Math.min(idx + 1, length) : idx + length + 1;
	        }
	      } else if (sortedIndex && idx && length) {
	        idx = sortedIndex(array, item);
	        return array[idx] === item ? idx : -1;
	      }
	      if (item !== item) {
	        idx = predicateFind(slice.call(array, i, length), _.isNaN);
	        return idx >= 0 ? idx + i : -1;
	      }
	      for (idx = dir > 0 ? i : length - 1; idx >= 0 && idx < length; idx += dir) {
	        if (array[idx] === item) return idx;
	      }
	      return -1;
	    };
	  }

	  // Return the position of the first occurrence of an item in an array,
	  // or -1 if the item is not included in the array.
	  // If the array is large and already in sort order, pass `true`
	  // for **isSorted** to use binary search.
	  _.indexOf = createIndexFinder(1, _.findIndex, _.sortedIndex);
	  _.lastIndexOf = createIndexFinder(-1, _.findLastIndex);

	  // Generate an integer Array containing an arithmetic progression. A port of
	  // the native Python `range()` function. See
	  // [the Python documentation](http://docs.python.org/library/functions.html#range).
	  _.range = function(start, stop, step) {
	    if (stop == null) {
	      stop = start || 0;
	      start = 0;
	    }
	    step = step || 1;

	    var length = Math.max(Math.ceil((stop - start) / step), 0);
	    var range = Array(length);

	    for (var idx = 0; idx < length; idx++, start += step) {
	      range[idx] = start;
	    }

	    return range;
	  };

	  // Function (ahem) Functions
	  // ------------------

	  // Determines whether to execute a function as a constructor
	  // or a normal function with the provided arguments
	  var executeBound = function(sourceFunc, boundFunc, context, callingContext, args) {
	    if (!(callingContext instanceof boundFunc)) return sourceFunc.apply(context, args);
	    var self = baseCreate(sourceFunc.prototype);
	    var result = sourceFunc.apply(self, args);
	    if (_.isObject(result)) return result;
	    return self;
	  };

	  // Create a function bound to a given object (assigning `this`, and arguments,
	  // optionally). Delegates to **ECMAScript 5**'s native `Function.bind` if
	  // available.
	  _.bind = function(func, context) {
	    if (nativeBind && func.bind === nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));
	    if (!_.isFunction(func)) throw new TypeError('Bind must be called on a function');
	    var args = slice.call(arguments, 2);
	    var bound = function() {
	      return executeBound(func, bound, context, this, args.concat(slice.call(arguments)));
	    };
	    return bound;
	  };

	  // Partially apply a function by creating a version that has had some of its
	  // arguments pre-filled, without changing its dynamic `this` context. _ acts
	  // as a placeholder, allowing any combination of arguments to be pre-filled.
	  _.partial = function(func) {
	    var boundArgs = slice.call(arguments, 1);
	    var bound = function() {
	      var position = 0, length = boundArgs.length;
	      var args = Array(length);
	      for (var i = 0; i < length; i++) {
	        args[i] = boundArgs[i] === _ ? arguments[position++] : boundArgs[i];
	      }
	      while (position < arguments.length) args.push(arguments[position++]);
	      return executeBound(func, bound, this, this, args);
	    };
	    return bound;
	  };

	  // Bind a number of an object's methods to that object. Remaining arguments
	  // are the method names to be bound. Useful for ensuring that all callbacks
	  // defined on an object belong to it.
	  _.bindAll = function(obj) {
	    var i, length = arguments.length, key;
	    if (length <= 1) throw new Error('bindAll must be passed function names');
	    for (i = 1; i < length; i++) {
	      key = arguments[i];
	      obj[key] = _.bind(obj[key], obj);
	    }
	    return obj;
	  };

	  // Memoize an expensive function by storing its results.
	  _.memoize = function(func, hasher) {
	    var memoize = function(key) {
	      var cache = memoize.cache;
	      var address = '' + (hasher ? hasher.apply(this, arguments) : key);
	      if (!_.has(cache, address)) cache[address] = func.apply(this, arguments);
	      return cache[address];
	    };
	    memoize.cache = {};
	    return memoize;
	  };

	  // Delays a function for the given number of milliseconds, and then calls
	  // it with the arguments supplied.
	  _.delay = function(func, wait) {
	    var args = slice.call(arguments, 2);
	    return setTimeout(function(){
	      return func.apply(null, args);
	    }, wait);
	  };

	  // Defers a function, scheduling it to run after the current call stack has
	  // cleared.
	  _.defer = _.partial(_.delay, _, 1);

	  // Returns a function, that, when invoked, will only be triggered at most once
	  // during a given window of time. Normally, the throttled function will run
	  // as much as it can, without ever going more than once per `wait` duration;
	  // but if you'd like to disable the execution on the leading edge, pass
	  // `{leading: false}`. To disable execution on the trailing edge, ditto.
	  _.throttle = function(func, wait, options) {
	    var context, args, result;
	    var timeout = null;
	    var previous = 0;
	    if (!options) options = {};
	    var later = function() {
	      previous = options.leading === false ? 0 : _.now();
	      timeout = null;
	      result = func.apply(context, args);
	      if (!timeout) context = args = null;
	    };
	    return function() {
	      var now = _.now();
	      if (!previous && options.leading === false) previous = now;
	      var remaining = wait - (now - previous);
	      context = this;
	      args = arguments;
	      if (remaining <= 0 || remaining > wait) {
	        if (timeout) {
	          clearTimeout(timeout);
	          timeout = null;
	        }
	        previous = now;
	        result = func.apply(context, args);
	        if (!timeout) context = args = null;
	      } else if (!timeout && options.trailing !== false) {
	        timeout = setTimeout(later, remaining);
	      }
	      return result;
	    };
	  };

	  // Returns a function, that, as long as it continues to be invoked, will not
	  // be triggered. The function will be called after it stops being called for
	  // N milliseconds. If `immediate` is passed, trigger the function on the
	  // leading edge, instead of the trailing.
	  _.debounce = function(func, wait, immediate) {
	    var timeout, args, context, timestamp, result;

	    var later = function() {
	      var last = _.now() - timestamp;

	      if (last < wait && last >= 0) {
	        timeout = setTimeout(later, wait - last);
	      } else {
	        timeout = null;
	        if (!immediate) {
	          result = func.apply(context, args);
	          if (!timeout) context = args = null;
	        }
	      }
	    };

	    return function() {
	      context = this;
	      args = arguments;
	      timestamp = _.now();
	      var callNow = immediate && !timeout;
	      if (!timeout) timeout = setTimeout(later, wait);
	      if (callNow) {
	        result = func.apply(context, args);
	        context = args = null;
	      }

	      return result;
	    };
	  };

	  // Returns the first function passed as an argument to the second,
	  // allowing you to adjust arguments, run code before and after, and
	  // conditionally execute the original function.
	  _.wrap = function(func, wrapper) {
	    return _.partial(wrapper, func);
	  };

	  // Returns a negated version of the passed-in predicate.
	  _.negate = function(predicate) {
	    return function() {
	      return !predicate.apply(this, arguments);
	    };
	  };

	  // Returns a function that is the composition of a list of functions, each
	  // consuming the return value of the function that follows.
	  _.compose = function() {
	    var args = arguments;
	    var start = args.length - 1;
	    return function() {
	      var i = start;
	      var result = args[start].apply(this, arguments);
	      while (i--) result = args[i].call(this, result);
	      return result;
	    };
	  };

	  // Returns a function that will only be executed on and after the Nth call.
	  _.after = function(times, func) {
	    return function() {
	      if (--times < 1) {
	        return func.apply(this, arguments);
	      }
	    };
	  };

	  // Returns a function that will only be executed up to (but not including) the Nth call.
	  _.before = function(times, func) {
	    var memo;
	    return function() {
	      if (--times > 0) {
	        memo = func.apply(this, arguments);
	      }
	      if (times <= 1) func = null;
	      return memo;
	    };
	  };

	  // Returns a function that will be executed at most one time, no matter how
	  // often you call it. Useful for lazy initialization.
	  _.once = _.partial(_.before, 2);

	  // Object Functions
	  // ----------------

	  // Keys in IE < 9 that won't be iterated by `for key in ...` and thus missed.
	  var hasEnumBug = !{toString: null}.propertyIsEnumerable('toString');
	  var nonEnumerableProps = ['valueOf', 'isPrototypeOf', 'toString',
	                      'propertyIsEnumerable', 'hasOwnProperty', 'toLocaleString'];

	  function collectNonEnumProps(obj, keys) {
	    var nonEnumIdx = nonEnumerableProps.length;
	    var constructor = obj.constructor;
	    var proto = (_.isFunction(constructor) && constructor.prototype) || ObjProto;

	    // Constructor is a special case.
	    var prop = 'constructor';
	    if (_.has(obj, prop) && !_.contains(keys, prop)) keys.push(prop);

	    while (nonEnumIdx--) {
	      prop = nonEnumerableProps[nonEnumIdx];
	      if (prop in obj && obj[prop] !== proto[prop] && !_.contains(keys, prop)) {
	        keys.push(prop);
	      }
	    }
	  }

	  // Retrieve the names of an object's own properties.
	  // Delegates to **ECMAScript 5**'s native `Object.keys`
	  _.keys = function(obj) {
	    if (!_.isObject(obj)) return [];
	    if (nativeKeys) return nativeKeys(obj);
	    var keys = [];
	    for (var key in obj) if (_.has(obj, key)) keys.push(key);
	    // Ahem, IE < 9.
	    if (hasEnumBug) collectNonEnumProps(obj, keys);
	    return keys;
	  };

	  // Retrieve all the property names of an object.
	  _.allKeys = function(obj) {
	    if (!_.isObject(obj)) return [];
	    var keys = [];
	    for (var key in obj) keys.push(key);
	    // Ahem, IE < 9.
	    if (hasEnumBug) collectNonEnumProps(obj, keys);
	    return keys;
	  };

	  // Retrieve the values of an object's properties.
	  _.values = function(obj) {
	    var keys = _.keys(obj);
	    var length = keys.length;
	    var values = Array(length);
	    for (var i = 0; i < length; i++) {
	      values[i] = obj[keys[i]];
	    }
	    return values;
	  };

	  // Returns the results of applying the iteratee to each element of the object
	  // In contrast to _.map it returns an object
	  _.mapObject = function(obj, iteratee, context) {
	    iteratee = cb(iteratee, context);
	    var keys =  _.keys(obj),
	          length = keys.length,
	          results = {},
	          currentKey;
	      for (var index = 0; index < length; index++) {
	        currentKey = keys[index];
	        results[currentKey] = iteratee(obj[currentKey], currentKey, obj);
	      }
	      return results;
	  };

	  // Convert an object into a list of `[key, value]` pairs.
	  _.pairs = function(obj) {
	    var keys = _.keys(obj);
	    var length = keys.length;
	    var pairs = Array(length);
	    for (var i = 0; i < length; i++) {
	      pairs[i] = [keys[i], obj[keys[i]]];
	    }
	    return pairs;
	  };

	  // Invert the keys and values of an object. The values must be serializable.
	  _.invert = function(obj) {
	    var result = {};
	    var keys = _.keys(obj);
	    for (var i = 0, length = keys.length; i < length; i++) {
	      result[obj[keys[i]]] = keys[i];
	    }
	    return result;
	  };

	  // Return a sorted list of the function names available on the object.
	  // Aliased as `methods`
	  _.functions = _.methods = function(obj) {
	    var names = [];
	    for (var key in obj) {
	      if (_.isFunction(obj[key])) names.push(key);
	    }
	    return names.sort();
	  };

	  // Extend a given object with all the properties in passed-in object(s).
	  _.extend = createAssigner(_.allKeys);

	  // Assigns a given object with all the own properties in the passed-in object(s)
	  // (https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/assign)
	  _.extendOwn = _.assign = createAssigner(_.keys);

	  // Returns the first key on an object that passes a predicate test
	  _.findKey = function(obj, predicate, context) {
	    predicate = cb(predicate, context);
	    var keys = _.keys(obj), key;
	    for (var i = 0, length = keys.length; i < length; i++) {
	      key = keys[i];
	      if (predicate(obj[key], key, obj)) return key;
	    }
	  };

	  // Return a copy of the object only containing the whitelisted properties.
	  _.pick = function(object, oiteratee, context) {
	    var result = {}, obj = object, iteratee, keys;
	    if (obj == null) return result;
	    if (_.isFunction(oiteratee)) {
	      keys = _.allKeys(obj);
	      iteratee = optimizeCb(oiteratee, context);
	    } else {
	      keys = flatten(arguments, false, false, 1);
	      iteratee = function(value, key, obj) { return key in obj; };
	      obj = Object(obj);
	    }
	    for (var i = 0, length = keys.length; i < length; i++) {
	      var key = keys[i];
	      var value = obj[key];
	      if (iteratee(value, key, obj)) result[key] = value;
	    }
	    return result;
	  };

	   // Return a copy of the object without the blacklisted properties.
	  _.omit = function(obj, iteratee, context) {
	    if (_.isFunction(iteratee)) {
	      iteratee = _.negate(iteratee);
	    } else {
	      var keys = _.map(flatten(arguments, false, false, 1), String);
	      iteratee = function(value, key) {
	        return !_.contains(keys, key);
	      };
	    }
	    return _.pick(obj, iteratee, context);
	  };

	  // Fill in a given object with default properties.
	  _.defaults = createAssigner(_.allKeys, true);

	  // Creates an object that inherits from the given prototype object.
	  // If additional properties are provided then they will be added to the
	  // created object.
	  _.create = function(prototype, props) {
	    var result = baseCreate(prototype);
	    if (props) _.extendOwn(result, props);
	    return result;
	  };

	  // Create a (shallow-cloned) duplicate of an object.
	  _.clone = function(obj) {
	    if (!_.isObject(obj)) return obj;
	    return _.isArray(obj) ? obj.slice() : _.extend({}, obj);
	  };

	  // Invokes interceptor with the obj, and then returns obj.
	  // The primary purpose of this method is to "tap into" a method chain, in
	  // order to perform operations on intermediate results within the chain.
	  _.tap = function(obj, interceptor) {
	    interceptor(obj);
	    return obj;
	  };

	  // Returns whether an object has a given set of `key:value` pairs.
	  _.isMatch = function(object, attrs) {
	    var keys = _.keys(attrs), length = keys.length;
	    if (object == null) return !length;
	    var obj = Object(object);
	    for (var i = 0; i < length; i++) {
	      var key = keys[i];
	      if (attrs[key] !== obj[key] || !(key in obj)) return false;
	    }
	    return true;
	  };


	  // Internal recursive comparison function for `isEqual`.
	  var eq = function(a, b, aStack, bStack) {
	    // Identical objects are equal. `0 === -0`, but they aren't identical.
	    // See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal).
	    if (a === b) return a !== 0 || 1 / a === 1 / b;
	    // A strict comparison is necessary because `null == undefined`.
	    if (a == null || b == null) return a === b;
	    // Unwrap any wrapped objects.
	    if (a instanceof _) a = a._wrapped;
	    if (b instanceof _) b = b._wrapped;
	    // Compare `[[Class]]` names.
	    var className = toString.call(a);
	    if (className !== toString.call(b)) return false;
	    switch (className) {
	      // Strings, numbers, regular expressions, dates, and booleans are compared by value.
	      case '[object RegExp]':
	      // RegExps are coerced to strings for comparison (Note: '' + /a/i === '/a/i')
	      case '[object String]':
	        // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is
	        // equivalent to `new String("5")`.
	        return '' + a === '' + b;
	      case '[object Number]':
	        // `NaN`s are equivalent, but non-reflexive.
	        // Object(NaN) is equivalent to NaN
	        if (+a !== +a) return +b !== +b;
	        // An `egal` comparison is performed for other numeric values.
	        return +a === 0 ? 1 / +a === 1 / b : +a === +b;
	      case '[object Date]':
	      case '[object Boolean]':
	        // Coerce dates and booleans to numeric primitive values. Dates are compared by their
	        // millisecond representations. Note that invalid dates with millisecond representations
	        // of `NaN` are not equivalent.
	        return +a === +b;
	    }

	    var areArrays = className === '[object Array]';
	    if (!areArrays) {
	      if (typeof a != 'object' || typeof b != 'object') return false;

	      // Objects with different constructors are not equivalent, but `Object`s or `Array`s
	      // from different frames are.
	      var aCtor = a.constructor, bCtor = b.constructor;
	      if (aCtor !== bCtor && !(_.isFunction(aCtor) && aCtor instanceof aCtor &&
	                               _.isFunction(bCtor) && bCtor instanceof bCtor)
	                          && ('constructor' in a && 'constructor' in b)) {
	        return false;
	      }
	    }
	    // Assume equality for cyclic structures. The algorithm for detecting cyclic
	    // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.

	    // Initializing stack of traversed objects.
	    // It's done here since we only need them for objects and arrays comparison.
	    aStack = aStack || [];
	    bStack = bStack || [];
	    var length = aStack.length;
	    while (length--) {
	      // Linear search. Performance is inversely proportional to the number of
	      // unique nested structures.
	      if (aStack[length] === a) return bStack[length] === b;
	    }

	    // Add the first object to the stack of traversed objects.
	    aStack.push(a);
	    bStack.push(b);

	    // Recursively compare objects and arrays.
	    if (areArrays) {
	      // Compare array lengths to determine if a deep comparison is necessary.
	      length = a.length;
	      if (length !== b.length) return false;
	      // Deep compare the contents, ignoring non-numeric properties.
	      while (length--) {
	        if (!eq(a[length], b[length], aStack, bStack)) return false;
	      }
	    } else {
	      // Deep compare objects.
	      var keys = _.keys(a), key;
	      length = keys.length;
	      // Ensure that both objects contain the same number of properties before comparing deep equality.
	      if (_.keys(b).length !== length) return false;
	      while (length--) {
	        // Deep compare each member
	        key = keys[length];
	        if (!(_.has(b, key) && eq(a[key], b[key], aStack, bStack))) return false;
	      }
	    }
	    // Remove the first object from the stack of traversed objects.
	    aStack.pop();
	    bStack.pop();
	    return true;
	  };

	  // Perform a deep comparison to check if two objects are equal.
	  _.isEqual = function(a, b) {
	    return eq(a, b);
	  };

	  // Is a given array, string, or object empty?
	  // An "empty" object has no enumerable own-properties.
	  _.isEmpty = function(obj) {
	    if (obj == null) return true;
	    if (isArrayLike(obj) && (_.isArray(obj) || _.isString(obj) || _.isArguments(obj))) return obj.length === 0;
	    return _.keys(obj).length === 0;
	  };

	  // Is a given value a DOM element?
	  _.isElement = function(obj) {
	    return !!(obj && obj.nodeType === 1);
	  };

	  // Is a given value an array?
	  // Delegates to ECMA5's native Array.isArray
	  _.isArray = nativeIsArray || function(obj) {
	    return toString.call(obj) === '[object Array]';
	  };

	  // Is a given variable an object?
	  _.isObject = function(obj) {
	    var type = typeof obj;
	    return type === 'function' || type === 'object' && !!obj;
	  };

	  // Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp, isError.
	  _.each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp', 'Error'], function(name) {
	    _['is' + name] = function(obj) {
	      return toString.call(obj) === '[object ' + name + ']';
	    };
	  });

	  // Define a fallback version of the method in browsers (ahem, IE < 9), where
	  // there isn't any inspectable "Arguments" type.
	  if (!_.isArguments(arguments)) {
	    _.isArguments = function(obj) {
	      return _.has(obj, 'callee');
	    };
	  }

	  // Optimize `isFunction` if appropriate. Work around some typeof bugs in old v8,
	  // IE 11 (#1621), and in Safari 8 (#1929).
	  if (typeof /./ != 'function' && typeof Int8Array != 'object') {
	    _.isFunction = function(obj) {
	      return typeof obj == 'function' || false;
	    };
	  }

	  // Is a given object a finite number?
	  _.isFinite = function(obj) {
	    return isFinite(obj) && !isNaN(parseFloat(obj));
	  };

	  // Is the given value `NaN`? (NaN is the only number which does not equal itself).
	  _.isNaN = function(obj) {
	    return _.isNumber(obj) && obj !== +obj;
	  };

	  // Is a given value a boolean?
	  _.isBoolean = function(obj) {
	    return obj === true || obj === false || toString.call(obj) === '[object Boolean]';
	  };

	  // Is a given value equal to null?
	  _.isNull = function(obj) {
	    return obj === null;
	  };

	  // Is a given variable undefined?
	  _.isUndefined = function(obj) {
	    return obj === void 0;
	  };

	  // Shortcut function for checking if an object has a given property directly
	  // on itself (in other words, not on a prototype).
	  _.has = function(obj, key) {
	    return obj != null && hasOwnProperty.call(obj, key);
	  };

	  // Utility Functions
	  // -----------------

	  // Run Underscore.js in *noConflict* mode, returning the `_` variable to its
	  // previous owner. Returns a reference to the Underscore object.
	  _.noConflict = function() {
	    root._ = previousUnderscore;
	    return this;
	  };

	  // Keep the identity function around for default iteratees.
	  _.identity = function(value) {
	    return value;
	  };

	  // Predicate-generating functions. Often useful outside of Underscore.
	  _.constant = function(value) {
	    return function() {
	      return value;
	    };
	  };

	  _.noop = function(){};

	  _.property = property;

	  // Generates a function for a given object that returns a given property.
	  _.propertyOf = function(obj) {
	    return obj == null ? function(){} : function(key) {
	      return obj[key];
	    };
	  };

	  // Returns a predicate for checking whether an object has a given set of
	  // `key:value` pairs.
	  _.matcher = _.matches = function(attrs) {
	    attrs = _.extendOwn({}, attrs);
	    return function(obj) {
	      return _.isMatch(obj, attrs);
	    };
	  };

	  // Run a function **n** times.
	  _.times = function(n, iteratee, context) {
	    var accum = Array(Math.max(0, n));
	    iteratee = optimizeCb(iteratee, context, 1);
	    for (var i = 0; i < n; i++) accum[i] = iteratee(i);
	    return accum;
	  };

	  // Return a random integer between min and max (inclusive).
	  _.random = function(min, max) {
	    if (max == null) {
	      max = min;
	      min = 0;
	    }
	    return min + Math.floor(Math.random() * (max - min + 1));
	  };

	  // A (possibly faster) way to get the current timestamp as an integer.
	  _.now = Date.now || function() {
	    return new Date().getTime();
	  };

	   // List of HTML entities for escaping.
	  var escapeMap = {
	    '&': '&amp;',
	    '<': '&lt;',
	    '>': '&gt;',
	    '"': '&quot;',
	    "'": '&#x27;',
	    '`': '&#x60;'
	  };
	  var unescapeMap = _.invert(escapeMap);

	  // Functions for escaping and unescaping strings to/from HTML interpolation.
	  var createEscaper = function(map) {
	    var escaper = function(match) {
	      return map[match];
	    };
	    // Regexes for identifying a key that needs to be escaped
	    var source = '(?:' + _.keys(map).join('|') + ')';
	    var testRegexp = RegExp(source);
	    var replaceRegexp = RegExp(source, 'g');
	    return function(string) {
	      string = string == null ? '' : '' + string;
	      return testRegexp.test(string) ? string.replace(replaceRegexp, escaper) : string;
	    };
	  };
	  _.escape = createEscaper(escapeMap);
	  _.unescape = createEscaper(unescapeMap);

	  // If the value of the named `property` is a function then invoke it with the
	  // `object` as context; otherwise, return it.
	  _.result = function(object, property, fallback) {
	    var value = object == null ? void 0 : object[property];
	    if (value === void 0) {
	      value = fallback;
	    }
	    return _.isFunction(value) ? value.call(object) : value;
	  };

	  // Generate a unique integer id (unique within the entire client session).
	  // Useful for temporary DOM ids.
	  var idCounter = 0;
	  _.uniqueId = function(prefix) {
	    var id = ++idCounter + '';
	    return prefix ? prefix + id : id;
	  };

	  // By default, Underscore uses ERB-style template delimiters, change the
	  // following template settings to use alternative delimiters.
	  _.templateSettings = {
	    evaluate    : /<%([\s\S]+?)%>/g,
	    interpolate : /<%=([\s\S]+?)%>/g,
	    escape      : /<%-([\s\S]+?)%>/g
	  };

	  // When customizing `templateSettings`, if you don't want to define an
	  // interpolation, evaluation or escaping regex, we need one that is
	  // guaranteed not to match.
	  var noMatch = /(.)^/;

	  // Certain characters need to be escaped so that they can be put into a
	  // string literal.
	  var escapes = {
	    "'":      "'",
	    '\\':     '\\',
	    '\r':     'r',
	    '\n':     'n',
	    '\u2028': 'u2028',
	    '\u2029': 'u2029'
	  };

	  var escaper = /\\|'|\r|\n|\u2028|\u2029/g;

	  var escapeChar = function(match) {
	    return '\\' + escapes[match];
	  };

	  // JavaScript micro-templating, similar to John Resig's implementation.
	  // Underscore templating handles arbitrary delimiters, preserves whitespace,
	  // and correctly escapes quotes within interpolated code.
	  // NB: `oldSettings` only exists for backwards compatibility.
	  _.template = function(text, settings, oldSettings) {
	    if (!settings && oldSettings) settings = oldSettings;
	    settings = _.defaults({}, settings, _.templateSettings);

	    // Combine delimiters into one regular expression via alternation.
	    var matcher = RegExp([
	      (settings.escape || noMatch).source,
	      (settings.interpolate || noMatch).source,
	      (settings.evaluate || noMatch).source
	    ].join('|') + '|$', 'g');

	    // Compile the template source, escaping string literals appropriately.
	    var index = 0;
	    var source = "__p+='";
	    text.replace(matcher, function(match, escape, interpolate, evaluate, offset) {
	      source += text.slice(index, offset).replace(escaper, escapeChar);
	      index = offset + match.length;

	      if (escape) {
	        source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'";
	      } else if (interpolate) {
	        source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'";
	      } else if (evaluate) {
	        source += "';\n" + evaluate + "\n__p+='";
	      }

	      // Adobe VMs need the match returned to produce the correct offest.
	      return match;
	    });
	    source += "';\n";

	    // If a variable is not specified, place data values in local scope.
	    if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n';

	    source = "var __t,__p='',__j=Array.prototype.join," +
	      "print=function(){__p+=__j.call(arguments,'');};\n" +
	      source + 'return __p;\n';

	    try {
	      var render = new Function(settings.variable || 'obj', '_', source);
	    } catch (e) {
	      e.source = source;
	      throw e;
	    }

	    var template = function(data) {
	      return render.call(this, data, _);
	    };

	    // Provide the compiled source as a convenience for precompilation.
	    var argument = settings.variable || 'obj';
	    template.source = 'function(' + argument + '){\n' + source + '}';

	    return template;
	  };

	  // Add a "chain" function. Start chaining a wrapped Underscore object.
	  _.chain = function(obj) {
	    var instance = _(obj);
	    instance._chain = true;
	    return instance;
	  };

	  // OOP
	  // ---------------
	  // If Underscore is called as a function, it returns a wrapped object that
	  // can be used OO-style. This wrapper holds altered versions of all the
	  // underscore functions. Wrapped objects may be chained.

	  // Helper function to continue chaining intermediate results.
	  var result = function(instance, obj) {
	    return instance._chain ? _(obj).chain() : obj;
	  };

	  // Add your own custom functions to the Underscore object.
	  _.mixin = function(obj) {
	    _.each(_.functions(obj), function(name) {
	      var func = _[name] = obj[name];
	      _.prototype[name] = function() {
	        var args = [this._wrapped];
	        push.apply(args, arguments);
	        return result(this, func.apply(_, args));
	      };
	    });
	  };

	  // Add all of the Underscore functions to the wrapper object.
	  _.mixin(_);

	  // Add all mutator Array functions to the wrapper.
	  _.each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {
	    var method = ArrayProto[name];
	    _.prototype[name] = function() {
	      var obj = this._wrapped;
	      method.apply(obj, arguments);
	      if ((name === 'shift' || name === 'splice') && obj.length === 0) delete obj[0];
	      return result(this, obj);
	    };
	  });

	  // Add all accessor Array functions to the wrapper.
	  _.each(['concat', 'join', 'slice'], function(name) {
	    var method = ArrayProto[name];
	    _.prototype[name] = function() {
	      return result(this, method.apply(this._wrapped, arguments));
	    };
	  });

	  // Extracts the result from a wrapped and chained object.
	  _.prototype.value = function() {
	    return this._wrapped;
	  };

	  // Provide unwrapping proxy for some methods used in engine operations
	  // such as arithmetic and JSON stringification.
	  _.prototype.valueOf = _.prototype.toJSON = _.prototype.value;

	  _.prototype.toString = function() {
	    return '' + this._wrapped;
	  };

	  // AMD registration happens at the end for compatibility with AMD loaders
	  // that may not enforce next-turn semantics on modules. Even though general
	  // practice for AMD registration is to be anonymous, underscore registers
	  // as a named module because, like jQuery, it is a base library that is
	  // popular enough to be bundled in a third party lib, but not be part of
	  // an AMD load request. Those cases could generate an error when an
	  // anonymous define() is called outside of a loader request.
	  if (true) {
	    !(__WEBPACK_AMD_DEFINE_ARRAY__ = [], __WEBPACK_AMD_DEFINE_RESULT__ = function() {
	      return _;
	    }.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
	  }
	}.call(this));


/***/ },
/* 7 */
/***/ function(module, exports, __webpack_require__) {

	var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(1)], __WEBPACK_AMD_DEFINE_RESULT__ = function(mp) {
	  'use strict';
	  var MailPoet = mp;
	  MailPoet.Iframe = {
	    marginY: 20,
	    autoSize: function(iframe) {
	      if(!iframe) return;

	      this.setSize(
	        iframe,
	        iframe.contentWindow.document.body.scrollHeight
	      );
	    },
	    setSize: function(sizeIframe, i) {
	      var iframe = sizeIframe;
	      if(!iframe) return;

	      iframe.style.height = (
	        parseInt(i, 10) + this.marginY
	      ) + "px";
	    }
	  };

	  return MailPoet;
	}.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));


/***/ },
/* 8 */
/***/ function(module, exports, __webpack_require__) {

	var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
	    __webpack_require__(4)
	  ], __WEBPACK_AMD_DEFINE_RESULT__ = function(
	    jQuery
	  ) {
	    var $ = jQuery;
	    // Combination of jQuery.deparam and jQuery.serializeObject by Ben Alman.
	    /*!
	     * jQuery BBQ: Back Button & Query Library - v1.2.1 - 2/17/2010
	     * http://benalman.com/projects/jquery-bbq-plugin/
	     *
	     * Copyright (c) 2010 "Cowboy" Ben Alman
	     * Dual licensed under the MIT and GPL licenses.
	     * http://benalman.com/about/license/
	     */
	    /*!
	     * jQuery serializeObject - v0.2 - 1/20/2010
	     * http://benalman.com/projects/jquery-misc-plugins/
	     *
	     * Copyright (c) 2010 "Cowboy" Ben Alman
	     * Dual licensed under the MIT and GPL licenses.
	     * http://benalman.com/about/license/
	     */
	    $.fn.serializeObject = function(coerce) {
	      var obj = {},
	        coerce_types = { 'true': !0, 'false': !1, 'null': null };

	      // Iterate over all name=value pairs.
	      $.each( this.serializeArray(), function(j, v){
	        var key = v.name,
	          val = v.value,
	          cur = obj,
	          i = 0,

	          // If key is more complex than 'foo', like 'a[]' or 'a[b][c]', split it
	          // into its component parts.
	          keys = key.split( '][' ),
	          keys_last = keys.length - 1;

	        // If the first keys part contains [ and the last ends with ], then []
	        // are correctly balanced.
	        if ( /\[/.test( keys[0] ) && /\]$/.test( keys[ keys_last ] ) ) {
	          // Remove the trailing ] from the last keys part.
	          keys[ keys_last ] = keys[ keys_last ].replace( /\]$/, '' );

	          // Split first keys part into two parts on the [ and add them back onto
	          // the beginning of the keys array.
	          keys = keys.shift().split('[').concat( keys );

	          keys_last = keys.length - 1;
	        } else {
	          // Basic 'foo' style key.
	          keys_last = 0;
	        }

	        // Coerce values.
	        if ( coerce ) {
	          val = val && !isNaN(val)            ? +val              // number
	            : val === 'undefined'             ? undefined         // undefined
	            : coerce_types[val] !== undefined ? coerce_types[val] // true, false, null
	            : val;                                                // string
	        }

	        if ( keys_last ) {
	          // Complex key, build deep object structure based on a few rules:
	          // * The 'cur' pointer starts at the object top-level.
	          // * [] = array push (n is set to array length), [n] = array if n is
	          //   numeric, otherwise object.
	          // * If at the last keys part, set the value.
	          // * For each keys part, if the current level is undefined create an
	          //   object or array based on the type of the next keys part.
	          // * Move the 'cur' pointer to the next level.
	          // * Rinse & repeat.
	          for ( ; i <= keys_last; i++ ) {
	            key = keys[i] === '' ? cur.length : keys[i];
	            cur[key] = i < keys_last
	              ? cur[key] || ( keys[i+1] && isNaN( keys[i+1] ) ? {} : [] )
	              : val;
	            cur = cur[key];
	          }

	        } else {
	          // Simple key, even simpler rules, since only scalars and shallow
	          // arrays are allowed.

	          if ( $.isArray( obj[key] ) ) {
	            // val is already an array, so push on the next value.
	            obj[key].push( val );

	          } else if ( obj[key] !== undefined ) {
	            // val isn't an array, but since a second value has been specified,
	            // convert val into an array.
	            obj[key] = [ obj[key], val ];

	          } else {
	            // val is a scalar.
	            obj[key] = val;
	          }
	        }
	      });

	      return obj;
	    };

	    return $;
	  }.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));

/***/ },
/* 9 */
/***/ function(module, exports, __webpack_require__) {

	var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
	  __webpack_require__(1),
	  __webpack_require__(4),
	  __webpack_require__(10)
	], __WEBPACK_AMD_DEFINE_RESULT__ = function(
	  MailPoet,
	  jQuery,
	  Parsley
	) {
	  jQuery(function($) {
	    function isSameDomain(url) {
	      var link = document.createElement('a');
	      link.href = url;
	      return (window.location.hostname === link.hostname);
	    }

	    $(function() {
	      // setup form validation
	      $('form.mailpoet_form').each(function() {
	        var form = $(this);

	        form.parsley().on('form:validated', function(parsley) {
	          // clear messages
	          form.find('.mailpoet_message > p').hide();

	          // resize iframe
	          if(window.frameElement !== null) {
	            MailPoet.Iframe.autoSize(window.frameElement);
	          }
	        });

	        form.parsley().on('form:submit', function(parsley) {
	          var form_data = form.serializeObject() || {};
	          // check if we're on the same domain
	          if(isSameDomain(MailPoetForm.ajax_url) === false) {
	            // non ajax post request
	            return true;
	          } else {
	            // ajax request
	            MailPoet.Ajax.post({
	              url: MailPoetForm.ajax_url,
	              token: form_data.token,
	              api_version: form_data.api_version,
	              endpoint: 'subscribers',
	              action: 'subscribe',
	              data: form_data.data
	            }).fail(function(response) {
	              form.find('.mailpoet_validate_error').html(
	                response.errors.map(function(error) {
	                  return error.message;
	                }).join('<br />')
	              ).show();
	            }).done(function(response) {
	              // successfully subscribed
	              if (
	                response.meta !== undefined
	                && response.meta.redirect_url !== undefined
	              ) {
	                // go to page
	                window.location.href = response.meta.redirect_url;
	              } else {
	                // display success message
	                form.find('.mailpoet_validate_success').show();
	              }

	              // reset form
	              form.trigger('reset');
	              // reset validation
	              parsley.reset();

	              // resize iframe
	              if (
	                window.frameElement !== null
	                && MailPoet !== undefined
	                && MailPoet['Iframe']
	              ) {
	                MailPoet.Iframe.autoSize(window.frameElement);
	              }
	            });
	          }
	          return false;
	        });
	      });
	    });
	  });
	}.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));

/***/ },
/* 10 */
/***/ function(module, exports, __webpack_require__) {

	/* WEBPACK VAR INJECTION */(function(global) {/*!
	* Parsley.js
	* Version 2.7.2 - built Tue, May 9th 2017, 11:21 am
	* http://parsleyjs.org
	* Guillaume Potier - <guillaume@wisembly.com>
	* Marc-Andre Lafortune - <petroselinum@marc-andre.ca>
	* MIT Licensed
	*/

	// The source code below is generated by babel as
	// Parsley is written in ECMAScript 6
	//
	var _slice = Array.prototype.slice;

	var _slicedToArray = (function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i['return']) _i['return'](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError('Invalid attempt to destructure non-iterable instance'); } }; })();

	var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };

	function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) arr2[i] = arr[i]; return arr2; } else { return Array.from(arr); } }

	(function (global, factory) {
	   true ? module.exports = factory(__webpack_require__(4)) : typeof define === 'function' && define.amd ? define(['jquery'], factory) : global.parsley = factory(global.jQuery);
	})(this, function ($) {
	  'use strict';

	  var globalID = 1;
	  var pastWarnings = {};

	  var Utils = {
	    // Parsley DOM-API
	    // returns object from dom attributes and values
	    attr: function attr(element, namespace, obj) {
	      var i;
	      var attribute;
	      var attributes;
	      var regex = new RegExp('^' + namespace, 'i');

	      if ('undefined' === typeof obj) obj = {};else {
	        // Clear all own properties. This won't affect prototype's values
	        for (i in obj) {
	          if (obj.hasOwnProperty(i)) delete obj[i];
	        }
	      }

	      if (!element) return obj;

	      attributes = element.attributes;
	      for (i = attributes.length; i--;) {
	        attribute = attributes[i];

	        if (attribute && attribute.specified && regex.test(attribute.name)) {
	          obj[this.camelize(attribute.name.slice(namespace.length))] = this.deserializeValue(attribute.value);
	        }
	      }

	      return obj;
	    },

	    checkAttr: function checkAttr(element, namespace, _checkAttr) {
	      return element.hasAttribute(namespace + _checkAttr);
	    },

	    setAttr: function setAttr(element, namespace, attr, value) {
	      element.setAttribute(this.dasherize(namespace + attr), String(value));
	    },

	    generateID: function generateID() {
	      return '' + globalID++;
	    },

	    /** Third party functions **/
	    // Zepto deserialize function
	    deserializeValue: function deserializeValue(value) {
	      var num;

	      try {
	        return value ? value == "true" || (value == "false" ? false : value == "null" ? null : !isNaN(num = Number(value)) ? num : /^[\[\{]/.test(value) ? $.parseJSON(value) : value) : value;
	      } catch (e) {
	        return value;
	      }
	    },

	    // Zepto camelize function
	    camelize: function camelize(str) {
	      return str.replace(/-+(.)?/g, function (match, chr) {
	        return chr ? chr.toUpperCase() : '';
	      });
	    },

	    // Zepto dasherize function
	    dasherize: function dasherize(str) {
	      return str.replace(/::/g, '/').replace(/([A-Z]+)([A-Z][a-z])/g, '$1_$2').replace(/([a-z\d])([A-Z])/g, '$1_$2').replace(/_/g, '-').toLowerCase();
	    },

	    warn: function warn() {
	      var _window$console;

	      if (window.console && 'function' === typeof window.console.warn) (_window$console = window.console).warn.apply(_window$console, arguments);
	    },

	    warnOnce: function warnOnce(msg) {
	      if (!pastWarnings[msg]) {
	        pastWarnings[msg] = true;
	        this.warn.apply(this, arguments);
	      }
	    },

	    _resetWarnings: function _resetWarnings() {
	      pastWarnings = {};
	    },

	    trimString: function trimString(string) {
	      return string.replace(/^\s+|\s+$/g, '');
	    },

	    parse: {
	      date: function date(string) {
	        var parsed = string.match(/^(\d{4,})-(\d\d)-(\d\d)$/);
	        if (!parsed) return null;

	        var _parsed$map = parsed.map(function (x) {
	          return parseInt(x, 10);
	        });

	        var _parsed$map2 = _slicedToArray(_parsed$map, 4);

	        var _ = _parsed$map2[0];
	        var year = _parsed$map2[1];
	        var month = _parsed$map2[2];
	        var day = _parsed$map2[3];

	        var date = new Date(year, month - 1, day);
	        if (date.getFullYear() !== year || date.getMonth() + 1 !== month || date.getDate() !== day) return null;
	        return date;
	      },
	      string: function string(_string) {
	        return _string;
	      },
	      integer: function integer(string) {
	        if (isNaN(string)) return null;
	        return parseInt(string, 10);
	      },
	      number: function number(string) {
	        if (isNaN(string)) throw null;
	        return parseFloat(string);
	      },
	      'boolean': function _boolean(string) {
	        return !/^\s*false\s*$/i.test(string);
	      },
	      object: function object(string) {
	        return Utils.deserializeValue(string);
	      },
	      regexp: function regexp(_regexp) {
	        var flags = '';

	        // Test if RegExp is literal, if not, nothing to be done, otherwise, we need to isolate flags and pattern
	        if (/^\/.*\/(?:[gimy]*)$/.test(_regexp)) {
	          // Replace the regexp literal string with the first match group: ([gimy]*)
	          // If no flag is present, this will be a blank string
	          flags = _regexp.replace(/.*\/([gimy]*)$/, '$1');
	          // Again, replace the regexp literal string with the first match group:
	          // everything excluding the opening and closing slashes and the flags
	          _regexp = _regexp.replace(new RegExp('^/(.*?)/' + flags + '$'), '$1');
	        } else {
	          // Anchor regexp:
	          _regexp = '^' + _regexp + '$';
	        }
	        return new RegExp(_regexp, flags);
	      }
	    },

	    parseRequirement: function parseRequirement(requirementType, string) {
	      var converter = this.parse[requirementType || 'string'];
	      if (!converter) throw 'Unknown requirement specification: "' + requirementType + '"';
	      var converted = converter(string);
	      if (converted === null) throw 'Requirement is not a ' + requirementType + ': "' + string + '"';
	      return converted;
	    },

	    namespaceEvents: function namespaceEvents(events, namespace) {
	      events = this.trimString(events || '').split(/\s+/);
	      if (!events[0]) return '';
	      return $.map(events, function (evt) {
	        return evt + '.' + namespace;
	      }).join(' ');
	    },

	    difference: function difference(array, remove) {
	      // This is O(N^2), should be optimized
	      var result = [];
	      $.each(array, function (_, elem) {
	        if (remove.indexOf(elem) == -1) result.push(elem);
	      });
	      return result;
	    },

	    // Alter-ego to native Promise.all, but for jQuery
	    all: function all(promises) {
	      // jQuery treats $.when() and $.when(singlePromise) differently; let's avoid that and add spurious elements
	      return $.when.apply($, _toConsumableArray(promises).concat([42, 42]));
	    },

	    // Object.create polyfill, see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create#Polyfill
	    objectCreate: Object.create || (function () {
	      var Object = function Object() {};
	      return function (prototype) {
	        if (arguments.length > 1) {
	          throw Error('Second argument not supported');
	        }
	        if (typeof prototype != 'object') {
	          throw TypeError('Argument must be an object');
	        }
	        Object.prototype = prototype;
	        var result = new Object();
	        Object.prototype = null;
	        return result;
	      };
	    })(),

	    _SubmitSelector: 'input[type="submit"], button:submit'
	  };

	  // All these options could be overriden and specified directly in DOM using
	  // `data-parsley-` default DOM-API
	  // eg: `inputs` can be set in DOM using `data-parsley-inputs="input, textarea"`
	  // eg: `data-parsley-stop-on-first-failing-constraint="false"`

	  var Defaults = {
	    // ### General

	    // Default data-namespace for DOM API
	    namespace: 'data-parsley-',

	    // Supported inputs by default
	    inputs: 'input, textarea, select',

	    // Excluded inputs by default
	    excluded: 'input[type=button], input[type=submit], input[type=reset], input[type=hidden]',

	    // Stop validating field on highest priority failing constraint
	    priorityEnabled: true,

	    // ### Field only

	    // identifier used to group together inputs (e.g. radio buttons...)
	    multiple: null,

	    // identifier (or array of identifiers) used to validate only a select group of inputs
	    group: null,

	    // ### UI
	    // Enable\Disable error messages
	    uiEnabled: true,

	    // Key events threshold before validation
	    validationThreshold: 3,

	    // Focused field on form validation error. 'first'|'last'|'none'
	    focus: 'first',

	    // event(s) that will trigger validation before first failure. eg: `input`...
	    trigger: false,

	    // event(s) that will trigger validation after first failure.
	    triggerAfterFailure: 'input',

	    // Class that would be added on every failing validation Parsley field
	    errorClass: 'parsley-error',

	    // Same for success validation
	    successClass: 'parsley-success',

	    // Return the `$element` that will receive these above success or error classes
	    // Could also be (and given directly from DOM) a valid selector like `'#div'`
	    classHandler: function classHandler(Field) {},

	    // Return the `$element` where errors will be appended
	    // Could also be (and given directly from DOM) a valid selector like `'#div'`
	    errorsContainer: function errorsContainer(Field) {},

	    // ul elem that would receive errors' list
	    errorsWrapper: '<ul class="parsley-errors-list"></ul>',

	    // li elem that would receive error message
	    errorTemplate: '<li></li>'
	  };

	  var Base = function Base() {
	    this.__id__ = Utils.generateID();
	  };

	  Base.prototype = {
	    asyncSupport: true, // Deprecated

	    _pipeAccordingToValidationResult: function _pipeAccordingToValidationResult() {
	      var _this = this;

	      var pipe = function pipe() {
	        var r = $.Deferred();
	        if (true !== _this.validationResult) r.reject();
	        return r.resolve().promise();
	      };
	      return [pipe, pipe];
	    },

	    actualizeOptions: function actualizeOptions() {
	      Utils.attr(this.element, this.options.namespace, this.domOptions);
	      if (this.parent && this.parent.actualizeOptions) this.parent.actualizeOptions();
	      return this;
	    },

	    _resetOptions: function _resetOptions(initOptions) {
	      this.domOptions = Utils.objectCreate(this.parent.options);
	      this.options = Utils.objectCreate(this.domOptions);
	      // Shallow copy of ownProperties of initOptions:
	      for (var i in initOptions) {
	        if (initOptions.hasOwnProperty(i)) this.options[i] = initOptions[i];
	      }
	      this.actualizeOptions();
	    },

	    _listeners: null,

	    // Register a callback for the given event name
	    // Callback is called with context as the first argument and the `this`
	    // The context is the current parsley instance, or window.Parsley if global
	    // A return value of `false` will interrupt the calls
	    on: function on(name, fn) {
	      this._listeners = this._listeners || {};
	      var queue = this._listeners[name] = this._listeners[name] || [];
	      queue.push(fn);

	      return this;
	    },

	    // Deprecated. Use `on` instead
	    subscribe: function subscribe(name, fn) {
	      $.listenTo(this, name.toLowerCase(), fn);
	    },

	    // Unregister a callback (or all if none is given) for the given event name
	    off: function off(name, fn) {
	      var queue = this._listeners && this._listeners[name];
	      if (queue) {
	        if (!fn) {
	          delete this._listeners[name];
	        } else {
	          for (var i = queue.length; i--;) if (queue[i] === fn) queue.splice(i, 1);
	        }
	      }
	      return this;
	    },

	    // Deprecated. Use `off`
	    unsubscribe: function unsubscribe(name, fn) {
	      $.unsubscribeTo(this, name.toLowerCase());
	    },

	    // Trigger an event of the given name
	    // A return value of `false` interrupts the callback chain
	    // Returns false if execution was interrupted
	    trigger: function trigger(name, target, extraArg) {
	      target = target || this;
	      var queue = this._listeners && this._listeners[name];
	      var result;
	      var parentResult;
	      if (queue) {
	        for (var i = queue.length; i--;) {
	          result = queue[i].call(target, target, extraArg);
	          if (result === false) return result;
	        }
	      }
	      if (this.parent) {
	        return this.parent.trigger(name, target, extraArg);
	      }
	      return true;
	    },

	    asyncIsValid: function asyncIsValid(group, force) {
	      Utils.warnOnce("asyncIsValid is deprecated; please use whenValid instead");
	      return this.whenValid({ group: group, force: force });
	    },

	    _findRelated: function _findRelated() {
	      return this.options.multiple ? $(this.parent.element.querySelectorAll('[' + this.options.namespace + 'multiple="' + this.options.multiple + '"]')) : this.$element;
	    }
	  };

	  var convertArrayRequirement = function convertArrayRequirement(string, length) {
	    var m = string.match(/^\s*\[(.*)\]\s*$/);
	    if (!m) throw 'Requirement is not an array: "' + string + '"';
	    var values = m[1].split(',').map(Utils.trimString);
	    if (values.length !== length) throw 'Requirement has ' + values.length + ' values when ' + length + ' are needed';
	    return values;
	  };

	  var convertExtraOptionRequirement = function convertExtraOptionRequirement(requirementSpec, string, extraOptionReader) {
	    var main = null;
	    var extra = {};
	    for (var key in requirementSpec) {
	      if (key) {
	        var value = extraOptionReader(key);
	        if ('string' === typeof value) value = Utils.parseRequirement(requirementSpec[key], value);
	        extra[key] = value;
	      } else {
	        main = Utils.parseRequirement(requirementSpec[key], string);
	      }
	    }
	    return [main, extra];
	  };

	  // A Validator needs to implement the methods `validate` and `parseRequirements`

	  var Validator = function Validator(spec) {
	    $.extend(true, this, spec);
	  };

	  Validator.prototype = {
	    // Returns `true` iff the given `value` is valid according the given requirements.
	    validate: function validate(value, requirementFirstArg) {
	      if (this.fn) {
	        // Legacy style validator

	        if (arguments.length > 3) // If more args then value, requirement, instance...
	          requirementFirstArg = [].slice.call(arguments, 1, -1); // Skip first arg (value) and last (instance), combining the rest
	        return this.fn(value, requirementFirstArg);
	      }

	      if (Array.isArray(value)) {
	        if (!this.validateMultiple) throw 'Validator `' + this.name + '` does not handle multiple values';
	        return this.validateMultiple.apply(this, arguments);
	      } else {
	        var instance = arguments[arguments.length - 1];
	        if (this.validateDate && instance._isDateInput()) {
	          arguments[0] = Utils.parse.date(arguments[0]);
	          if (arguments[0] === null) return false;
	          return this.validateDate.apply(this, arguments);
	        }
	        if (this.validateNumber) {
	          if (isNaN(value)) return false;
	          arguments[0] = parseFloat(arguments[0]);
	          return this.validateNumber.apply(this, arguments);
	        }
	        if (this.validateString) {
	          return this.validateString.apply(this, arguments);
	        }
	        throw 'Validator `' + this.name + '` only handles multiple values';
	      }
	    },

	    // Parses `requirements` into an array of arguments,
	    // according to `this.requirementType`
	    parseRequirements: function parseRequirements(requirements, extraOptionReader) {
	      if ('string' !== typeof requirements) {
	        // Assume requirement already parsed
	        // but make sure we return an array
	        return Array.isArray(requirements) ? requirements : [requirements];
	      }
	      var type = this.requirementType;
	      if (Array.isArray(type)) {
	        var values = convertArrayRequirement(requirements, type.length);
	        for (var i = 0; i < values.length; i++) values[i] = Utils.parseRequirement(type[i], values[i]);
	        return values;
	      } else if ($.isPlainObject(type)) {
	        return convertExtraOptionRequirement(type, requirements, extraOptionReader);
	      } else {
	        return [Utils.parseRequirement(type, requirements)];
	      }
	    },
	    // Defaults:
	    requirementType: 'string',

	    priority: 2

	  };

	  var ValidatorRegistry = function ValidatorRegistry(validators, catalog) {
	    this.__class__ = 'ValidatorRegistry';

	    // Default Parsley locale is en
	    this.locale = 'en';

	    this.init(validators || {}, catalog || {});
	  };

	  var typeTesters = {
	    email: /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))$/i,

	    // Follow https://www.w3.org/TR/html5/infrastructure.html#floating-point-numbers
	    number: /^-?(\d*\.)?\d+(e[-+]?\d+)?$/i,

	    integer: /^-?\d+$/,

	    digits: /^\d+$/,

	    alphanum: /^\w+$/i,

	    date: {
	      test: function test(value) {
	        return Utils.parse.date(value) !== null;
	      }
	    },

	    url: new RegExp("^" +
	    // protocol identifier
	    "(?:(?:https?|ftp)://)?" + // ** mod: make scheme optional
	    // user:pass authentication
	    "(?:\\S+(?::\\S*)?@)?" + "(?:" +
	    // IP address exclusion
	    // private & local networks
	    // "(?!(?:10|127)(?:\\.\\d{1,3}){3})" +   // ** mod: allow local networks
	    // "(?!(?:169\\.254|192\\.168)(?:\\.\\d{1,3}){2})" +  // ** mod: allow local networks
	    // "(?!172\\.(?:1[6-9]|2\\d|3[0-1])(?:\\.\\d{1,3}){2})" +  // ** mod: allow local networks
	    // IP address dotted notation octets
	    // excludes loopback network 0.0.0.0
	    // excludes reserved space >= 224.0.0.0
	    // excludes network & broacast addresses
	    // (first & last IP address of each class)
	    "(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])" + "(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}" + "(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))" + "|" +
	    // host name
	    '(?:(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)' +
	    // domain name
	    '(?:\\.(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)*' +
	    // TLD identifier
	    '(?:\\.(?:[a-z\\u00a1-\\uffff]{2,}))' + ")" +
	    // port number
	    "(?::\\d{2,5})?" +
	    // resource path
	    "(?:/\\S*)?" + "$", 'i')
	  };
	  typeTesters.range = typeTesters.number;

	  // See http://stackoverflow.com/a/10454560/8279
	  var decimalPlaces = function decimalPlaces(num) {
	    var match = ('' + num).match(/(?:\.(\d+))?(?:[eE]([+-]?\d+))?$/);
	    if (!match) {
	      return 0;
	    }
	    return Math.max(0,
	    // Number of digits right of decimal point.
	    (match[1] ? match[1].length : 0) - (
	    // Adjust for scientific notation.
	    match[2] ? +match[2] : 0));
	  };

	  // parseArguments('number', ['1', '2']) => [1, 2]
	  var ValidatorRegistry__parseArguments = function ValidatorRegistry__parseArguments(type, args) {
	    return args.map(Utils.parse[type]);
	  };
	  // operatorToValidator returns a validating function for an operator function, applied to the given type
	  var ValidatorRegistry__operatorToValidator = function ValidatorRegistry__operatorToValidator(type, operator) {
	    return function (value) {
	      for (var _len = arguments.length, requirementsAndInput = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
	        requirementsAndInput[_key - 1] = arguments[_key];
	      }

	      requirementsAndInput.pop(); // Get rid of `input` argument
	      return operator.apply(undefined, [value].concat(_toConsumableArray(ValidatorRegistry__parseArguments(type, requirementsAndInput))));
	    };
	  };

	  var ValidatorRegistry__comparisonOperator = function ValidatorRegistry__comparisonOperator(operator) {
	    return {
	      validateDate: ValidatorRegistry__operatorToValidator('date', operator),
	      validateNumber: ValidatorRegistry__operatorToValidator('number', operator),
	      requirementType: operator.length <= 2 ? 'string' : ['string', 'string'], // Support operators with a 1 or 2 requirement(s)
	      priority: 30
	    };
	  };

	  ValidatorRegistry.prototype = {
	    init: function init(validators, catalog) {
	      this.catalog = catalog;
	      // Copy prototype's validators:
	      this.validators = _extends({}, this.validators);

	      for (var name in validators) this.addValidator(name, validators[name].fn, validators[name].priority);

	      window.Parsley.trigger('parsley:validator:init');
	    },

	    // Set new messages locale if we have dictionary loaded in ParsleyConfig.i18n
	    setLocale: function setLocale(locale) {
	      if ('undefined' === typeof this.catalog[locale]) throw new Error(locale + ' is not available in the catalog');

	      this.locale = locale;

	      return this;
	    },

	    // Add a new messages catalog for a given locale. Set locale for this catalog if set === `true`
	    addCatalog: function addCatalog(locale, messages, set) {
	      if ('object' === typeof messages) this.catalog[locale] = messages;

	      if (true === set) return this.setLocale(locale);

	      return this;
	    },

	    // Add a specific message for a given constraint in a given locale
	    addMessage: function addMessage(locale, name, message) {
	      if ('undefined' === typeof this.catalog[locale]) this.catalog[locale] = {};

	      this.catalog[locale][name] = message;

	      return this;
	    },

	    // Add messages for a given locale
	    addMessages: function addMessages(locale, nameMessageObject) {
	      for (var name in nameMessageObject) this.addMessage(locale, name, nameMessageObject[name]);

	      return this;
	    },

	    // Add a new validator
	    //
	    //    addValidator('custom', {
	    //        requirementType: ['integer', 'integer'],
	    //        validateString: function(value, from, to) {},
	    //        priority: 22,
	    //        messages: {
	    //          en: "Hey, that's no good",
	    //          fr: "Aye aye, pas bon du tout",
	    //        }
	    //    })
	    //
	    // Old API was addValidator(name, function, priority)
	    //
	    addValidator: function addValidator(name, arg1, arg2) {
	      if (this.validators[name]) Utils.warn('Validator "' + name + '" is already defined.');else if (Defaults.hasOwnProperty(name)) {
	        Utils.warn('"' + name + '" is a restricted keyword and is not a valid validator name.');
	        return;
	      }
	      return this._setValidator.apply(this, arguments);
	    },

	    updateValidator: function updateValidator(name, arg1, arg2) {
	      if (!this.validators[name]) {
	        Utils.warn('Validator "' + name + '" is not already defined.');
	        return this.addValidator.apply(this, arguments);
	      }
	      return this._setValidator.apply(this, arguments);
	    },

	    removeValidator: function removeValidator(name) {
	      if (!this.validators[name]) Utils.warn('Validator "' + name + '" is not defined.');

	      delete this.validators[name];

	      return this;
	    },

	    _setValidator: function _setValidator(name, validator, priority) {
	      if ('object' !== typeof validator) {
	        // Old style validator, with `fn` and `priority`
	        validator = {
	          fn: validator,
	          priority: priority
	        };
	      }
	      if (!validator.validate) {
	        validator = new Validator(validator);
	      }
	      this.validators[name] = validator;

	      for (var locale in validator.messages || {}) this.addMessage(locale, name, validator.messages[locale]);

	      return this;
	    },

	    getErrorMessage: function getErrorMessage(constraint) {
	      var message;

	      // Type constraints are a bit different, we have to match their requirements too to find right error message
	      if ('type' === constraint.name) {
	        var typeMessages = this.catalog[this.locale][constraint.name] || {};
	        message = typeMessages[constraint.requirements];
	      } else message = this.formatMessage(this.catalog[this.locale][constraint.name], constraint.requirements);

	      return message || this.catalog[this.locale].defaultMessage || this.catalog.en.defaultMessage;
	    },

	    // Kind of light `sprintf()` implementation
	    formatMessage: function formatMessage(string, parameters) {
	      if ('object' === typeof parameters) {
	        for (var i in parameters) string = this.formatMessage(string, parameters[i]);

	        return string;
	      }

	      return 'string' === typeof string ? string.replace(/%s/i, parameters) : '';
	    },

	    // Here is the Parsley default validators list.
	    // A validator is an object with the following key values:
	    //  - priority: an integer
	    //  - requirement: 'string' (default), 'integer', 'number', 'regexp' or an Array of these
	    //  - validateString, validateMultiple, validateNumber: functions returning `true`, `false` or a promise
	    // Alternatively, a validator can be a function that returns such an object
	    //
	    validators: {
	      notblank: {
	        validateString: function validateString(value) {
	          return (/\S/.test(value)
	          );
	        },
	        priority: 2
	      },
	      required: {
	        validateMultiple: function validateMultiple(values) {
	          return values.length > 0;
	        },
	        validateString: function validateString(value) {
	          return (/\S/.test(value)
	          );
	        },
	        priority: 512
	      },
	      type: {
	        validateString: function validateString(value, type) {
	          var _ref = arguments.length <= 2 || arguments[2] === undefined ? {} : arguments[2];

	          var _ref$step = _ref.step;
	          var step = _ref$step === undefined ? 'any' : _ref$step;
	          var _ref$base = _ref.base;
	          var base = _ref$base === undefined ? 0 : _ref$base;

	          var tester = typeTesters[type];
	          if (!tester) {
	            throw new Error('validator type `' + type + '` is not supported');
	          }
	          if (!tester.test(value)) return false;
	          if ('number' === type) {
	            if (!/^any$/i.test(step || '')) {
	              var nb = Number(value);
	              var decimals = Math.max(decimalPlaces(step), decimalPlaces(base));
	              if (decimalPlaces(nb) > decimals) // Value can't have too many decimals
	                return false;
	              // Be careful of rounding errors by using integers.
	              var toInt = function toInt(f) {
	                return Math.round(f * Math.pow(10, decimals));
	              };
	              if ((toInt(nb) - toInt(base)) % toInt(step) != 0) return false;
	            }
	          }
	          return true;
	        },
	        requirementType: {
	          '': 'string',
	          step: 'string',
	          base: 'number'
	        },
	        priority: 256
	      },
	      pattern: {
	        validateString: function validateString(value, regexp) {
	          return regexp.test(value);
	        },
	        requirementType: 'regexp',
	        priority: 64
	      },
	      minlength: {
	        validateString: function validateString(value, requirement) {
	          return value.length >= requirement;
	        },
	        requirementType: 'integer',
	        priority: 30
	      },
	      maxlength: {
	        validateString: function validateString(value, requirement) {
	          return value.length <= requirement;
	        },
	        requirementType: 'integer',
	        priority: 30
	      },
	      length: {
	        validateString: function validateString(value, min, max) {
	          return value.length >= min && value.length <= max;
	        },
	        requirementType: ['integer', 'integer'],
	        priority: 30
	      },
	      mincheck: {
	        validateMultiple: function validateMultiple(values, requirement) {
	          return values.length >= requirement;
	        },
	        requirementType: 'integer',
	        priority: 30
	      },
	      maxcheck: {
	        validateMultiple: function validateMultiple(values, requirement) {
	          return values.length <= requirement;
	        },
	        requirementType: 'integer',
	        priority: 30
	      },
	      check: {
	        validateMultiple: function validateMultiple(values, min, max) {
	          return values.length >= min && values.length <= max;
	        },
	        requirementType: ['integer', 'integer'],
	        priority: 30
	      },
	      min: ValidatorRegistry__comparisonOperator(function (value, requirement) {
	        return value >= requirement;
	      }),
	      max: ValidatorRegistry__comparisonOperator(function (value, requirement) {
	        return value <= requirement;
	      }),
	      range: ValidatorRegistry__comparisonOperator(function (value, min, max) {
	        return value >= min && value <= max;
	      }),
	      equalto: {
	        validateString: function validateString(value, refOrValue) {
	          var $reference = $(refOrValue);
	          if ($reference.length) return value === $reference.val();else return value === refOrValue;
	        },
	        priority: 256
	      }
	    }
	  };

	  var UI = {};

	  var diffResults = function diffResults(newResult, oldResult, deep) {
	    var added = [];
	    var kept = [];

	    for (var i = 0; i < newResult.length; i++) {
	      var found = false;

	      for (var j = 0; j < oldResult.length; j++) if (newResult[i].assert.name === oldResult[j].assert.name) {
	        found = true;
	        break;
	      }

	      if (found) kept.push(newResult[i]);else added.push(newResult[i]);
	    }

	    return {
	      kept: kept,
	      added: added,
	      removed: !deep ? diffResults(oldResult, newResult, true).added : []
	    };
	  };

	  UI.Form = {

	    _actualizeTriggers: function _actualizeTriggers() {
	      var _this2 = this;

	      this.$element.on('submit.Parsley', function (evt) {
	        _this2.onSubmitValidate(evt);
	      });
	      this.$element.on('click.Parsley', Utils._SubmitSelector, function (evt) {
	        _this2.onSubmitButton(evt);
	      });

	      // UI could be disabled
	      if (false === this.options.uiEnabled) return;

	      this.element.setAttribute('novalidate', '');
	    },

	    focus: function focus() {
	      this._focusedField = null;

	      if (true === this.validationResult || 'none' === this.options.focus) return null;

	      for (var i = 0; i < this.fields.length; i++) {
	        var field = this.fields[i];
	        if (true !== field.validationResult && field.validationResult.length > 0 && 'undefined' === typeof field.options.noFocus) {
	          this._focusedField = field.$element;
	          if ('first' === this.options.focus) break;
	        }
	      }

	      if (null === this._focusedField) return null;

	      return this._focusedField.focus();
	    },

	    _destroyUI: function _destroyUI() {
	      // Reset all event listeners
	      this.$element.off('.Parsley');
	    }

	  };

	  UI.Field = {

	    _reflowUI: function _reflowUI() {
	      this._buildUI();

	      // If this field doesn't have an active UI don't bother doing something
	      if (!this._ui) return;

	      // Diff between two validation results
	      var diff = diffResults(this.validationResult, this._ui.lastValidationResult);

	      // Then store current validation result for next reflow
	      this._ui.lastValidationResult = this.validationResult;

	      // Handle valid / invalid / none field class
	      this._manageStatusClass();

	      // Add, remove, updated errors messages
	      this._manageErrorsMessages(diff);

	      // Triggers impl
	      this._actualizeTriggers();

	      // If field is not valid for the first time, bind keyup trigger to ease UX and quickly inform user
	      if ((diff.kept.length || diff.added.length) && !this._failedOnce) {
	        this._failedOnce = true;
	        this._actualizeTriggers();
	      }
	    },

	    // Returns an array of field's error message(s)
	    getErrorsMessages: function getErrorsMessages() {
	      // No error message, field is valid
	      if (true === this.validationResult) return [];

	      var messages = [];

	      for (var i = 0; i < this.validationResult.length; i++) messages.push(this.validationResult[i].errorMessage || this._getErrorMessage(this.validationResult[i].assert));

	      return messages;
	    },

	    // It's a goal of Parsley that this method is no longer required [#1073]
	    addError: function addError(name) {
	      var _ref2 = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];

	      var message = _ref2.message;
	      var assert = _ref2.assert;
	      var _ref2$updateClass = _ref2.updateClass;
	      var updateClass = _ref2$updateClass === undefined ? true : _ref2$updateClass;

	      this._buildUI();
	      this._addError(name, { message: message, assert: assert });

	      if (updateClass) this._errorClass();
	    },

	    // It's a goal of Parsley that this method is no longer required [#1073]
	    updateError: function updateError(name) {
	      var _ref3 = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];

	      var message = _ref3.message;
	      var assert = _ref3.assert;
	      var _ref3$updateClass = _ref3.updateClass;
	      var updateClass = _ref3$updateClass === undefined ? true : _ref3$updateClass;

	      this._buildUI();
	      this._updateError(name, { message: message, assert: assert });

	      if (updateClass) this._errorClass();
	    },

	    // It's a goal of Parsley that this method is no longer required [#1073]
	    removeError: function removeError(name) {
	      var _ref4 = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];

	      var _ref4$updateClass = _ref4.updateClass;
	      var updateClass = _ref4$updateClass === undefined ? true : _ref4$updateClass;

	      this._buildUI();
	      this._removeError(name);

	      // edge case possible here: remove a standard Parsley error that is still failing in this.validationResult
	      // but highly improbable cuz' manually removing a well Parsley handled error makes no sense.
	      if (updateClass) this._manageStatusClass();
	    },

	    _manageStatusClass: function _manageStatusClass() {
	      if (this.hasConstraints() && this.needsValidation() && true === this.validationResult) this._successClass();else if (this.validationResult.length > 0) this._errorClass();else this._resetClass();
	    },

	    _manageErrorsMessages: function _manageErrorsMessages(diff) {
	      if ('undefined' !== typeof this.options.errorsMessagesDisabled) return;

	      // Case where we have errorMessage option that configure an unique field error message, regardless failing validators
	      if ('undefined' !== typeof this.options.errorMessage) {
	        if (diff.added.length || diff.kept.length) {
	          this._insertErrorWrapper();

	          if (0 === this._ui.$errorsWrapper.find('.parsley-custom-error-message').length) this._ui.$errorsWrapper.append($(this.options.errorTemplate).addClass('parsley-custom-error-message'));

	          return this._ui.$errorsWrapper.addClass('filled').find('.parsley-custom-error-message').html(this.options.errorMessage);
	        }

	        return this._ui.$errorsWrapper.removeClass('filled').find('.parsley-custom-error-message').remove();
	      }

	      // Show, hide, update failing constraints messages
	      for (var i = 0; i < diff.removed.length; i++) this._removeError(diff.removed[i].assert.name);

	      for (i = 0; i < diff.added.length; i++) this._addError(diff.added[i].assert.name, { message: diff.added[i].errorMessage, assert: diff.added[i].assert });

	      for (i = 0; i < diff.kept.length; i++) this._updateError(diff.kept[i].assert.name, { message: diff.kept[i].errorMessage, assert: diff.kept[i].assert });
	    },

	    _addError: function _addError(name, _ref5) {
	      var message = _ref5.message;
	      var assert = _ref5.assert;

	      this._insertErrorWrapper();
	      this._ui.$errorsWrapper.addClass('filled').append($(this.options.errorTemplate).addClass('parsley-' + name).html(message || this._getErrorMessage(assert)));
	    },

	    _updateError: function _updateError(name, _ref6) {
	      var message = _ref6.message;
	      var assert = _ref6.assert;

	      this._ui.$errorsWrapper.addClass('filled').find('.parsley-' + name).html(message || this._getErrorMessage(assert));
	    },

	    _removeError: function _removeError(name) {
	      this._ui.$errorsWrapper.removeClass('filled').find('.parsley-' + name).remove();
	    },

	    _getErrorMessage: function _getErrorMessage(constraint) {
	      var customConstraintErrorMessage = constraint.name + 'Message';

	      if ('undefined' !== typeof this.options[customConstraintErrorMessage]) return window.Parsley.formatMessage(this.options[customConstraintErrorMessage], constraint.requirements);

	      return window.Parsley.getErrorMessage(constraint);
	    },

	    _buildUI: function _buildUI() {
	      // UI could be already built or disabled
	      if (this._ui || false === this.options.uiEnabled) return;

	      var _ui = {};

	      // Give field its Parsley id in DOM
	      this.element.setAttribute(this.options.namespace + 'id', this.__id__);

	      /** Generate important UI elements and store them in this **/
	      // $errorClassHandler is the $element that woul have parsley-error and parsley-success classes
	      _ui.$errorClassHandler = this._manageClassHandler();

	      // $errorsWrapper is a div that would contain the various field errors, it will be appended into $errorsContainer
	      _ui.errorsWrapperId = 'parsley-id-' + (this.options.multiple ? 'multiple-' + this.options.multiple : this.__id__);
	      _ui.$errorsWrapper = $(this.options.errorsWrapper).attr('id', _ui.errorsWrapperId);

	      // ValidationResult UI storage to detect what have changed bwt two validations, and update DOM accordingly
	      _ui.lastValidationResult = [];
	      _ui.validationInformationVisible = false;

	      // Store it in this for later
	      this._ui = _ui;
	    },

	    // Determine which element will have `parsley-error` and `parsley-success` classes
	    _manageClassHandler: function _manageClassHandler() {
	      // An element selector could be passed through DOM with `data-parsley-class-handler=#foo`
	      if ('string' === typeof this.options.classHandler) {
	        if ($(this.options.classHandler).length === 0) ParsleyUtils.warn('No elements found that match the selector `' + this.options.classHandler + '` set in options.classHandler or data-parsley-class-handler');

	        //return element or empty set
	        return $(this.options.classHandler);
	      }

	      // Class handled could also be determined by function given in Parsley options
	      if ('function' === typeof this.options.classHandler) var $handler = this.options.classHandler.call(this, this);

	      // If this function returned a valid existing DOM element, go for it
	      if ('undefined' !== typeof $handler && $handler.length) return $handler;

	      return this._inputHolder();
	    },

	    _inputHolder: function _inputHolder() {
	      // if simple element (input, texatrea, select...) it will perfectly host the classes and precede the error container
	      if (!this.options.multiple || this.element.nodeName === 'SELECT') return this.$element;

	      // But if multiple element (radio, checkbox), that would be their parent
	      return this.$element.parent();
	    },

	    _insertErrorWrapper: function _insertErrorWrapper() {
	      var $errorsContainer;

	      // Nothing to do if already inserted
	      if (0 !== this._ui.$errorsWrapper.parent().length) return this._ui.$errorsWrapper.parent();

	      if ('string' === typeof this.options.errorsContainer) {
	        if ($(this.options.errorsContainer).length) return $(this.options.errorsContainer).append(this._ui.$errorsWrapper);else Utils.warn('The errors container `' + this.options.errorsContainer + '` does not exist in DOM');
	      } else if ('function' === typeof this.options.errorsContainer) $errorsContainer = this.options.errorsContainer.call(this, this);

	      if ('undefined' !== typeof $errorsContainer && $errorsContainer.length) return $errorsContainer.append(this._ui.$errorsWrapper);

	      return this._inputHolder().after(this._ui.$errorsWrapper);
	    },

	    _actualizeTriggers: function _actualizeTriggers() {
	      var _this3 = this;

	      var $toBind = this._findRelated();
	      var trigger;

	      // Remove Parsley events already bound on this field
	      $toBind.off('.Parsley');
	      if (this._failedOnce) $toBind.on(Utils.namespaceEvents(this.options.triggerAfterFailure, 'Parsley'), function () {
	        _this3._validateIfNeeded();
	      });else if (trigger = Utils.namespaceEvents(this.options.trigger, 'Parsley')) {
	        $toBind.on(trigger, function (event) {
	          _this3._validateIfNeeded(event);
	        });
	      }
	    },

	    _validateIfNeeded: function _validateIfNeeded(event) {
	      var _this4 = this;

	      // For keyup, keypress, keydown, input... events that could be a little bit obstrusive
	      // do not validate if val length < min threshold on first validation. Once field have been validated once and info
	      // about success or failure have been displayed, always validate with this trigger to reflect every yalidation change.
	      if (event && /key|input/.test(event.type)) if (!(this._ui && this._ui.validationInformationVisible) && this.getValue().length <= this.options.validationThreshold) return;

	      if (this.options.debounce) {
	        window.clearTimeout(this._debounced);
	        this._debounced = window.setTimeout(function () {
	          return _this4.validate();
	        }, this.options.debounce);
	      } else this.validate();
	    },

	    _resetUI: function _resetUI() {
	      // Reset all event listeners
	      this._failedOnce = false;
	      this._actualizeTriggers();

	      // Nothing to do if UI never initialized for this field
	      if ('undefined' === typeof this._ui) return;

	      // Reset all errors' li
	      this._ui.$errorsWrapper.removeClass('filled').children().remove();

	      // Reset validation class
	      this._resetClass();

	      // Reset validation flags and last validation result
	      this._ui.lastValidationResult = [];
	      this._ui.validationInformationVisible = false;
	    },

	    _destroyUI: function _destroyUI() {
	      this._resetUI();

	      if ('undefined' !== typeof this._ui) this._ui.$errorsWrapper.remove();

	      delete this._ui;
	    },

	    _successClass: function _successClass() {
	      this._ui.validationInformationVisible = true;
	      this._ui.$errorClassHandler.removeClass(this.options.errorClass).addClass(this.options.successClass);
	    },
	    _errorClass: function _errorClass() {
	      this._ui.validationInformationVisible = true;
	      this._ui.$errorClassHandler.removeClass(this.options.successClass).addClass(this.options.errorClass);
	    },
	    _resetClass: function _resetClass() {
	      this._ui.$errorClassHandler.removeClass(this.options.successClass).removeClass(this.options.errorClass);
	    }
	  };

	  var Form = function Form(element, domOptions, options) {
	    this.__class__ = 'Form';

	    this.element = element;
	    this.$element = $(element);
	    this.domOptions = domOptions;
	    this.options = options;
	    this.parent = window.Parsley;

	    this.fields = [];
	    this.validationResult = null;
	  };

	  var Form__statusMapping = { pending: null, resolved: true, rejected: false };

	  Form.prototype = {
	    onSubmitValidate: function onSubmitValidate(event) {
	      var _this5 = this;

	      // This is a Parsley generated submit event, do not validate, do not prevent, simply exit and keep normal behavior
	      if (true === event.parsley) return;

	      // If we didn't come here through a submit button, use the first one in the form
	      var submitSource = this._submitSource || this.$element.find(Utils._SubmitSelector)[0];
	      this._submitSource = null;
	      this.$element.find('.parsley-synthetic-submit-button').prop('disabled', true);
	      if (submitSource && null !== submitSource.getAttribute('formnovalidate')) return;

	      window.Parsley._remoteCache = {};

	      var promise = this.whenValidate({ event: event });

	      if ('resolved' === promise.state() && false !== this._trigger('submit')) {
	        // All good, let event go through. We make this distinction because browsers
	        // differ in their handling of `submit` being called from inside a submit event [#1047]
	      } else {
	          // Rejected or pending: cancel this submit
	          event.stopImmediatePropagation();
	          event.preventDefault();
	          if ('pending' === promise.state()) promise.done(function () {
	            _this5._submit(submitSource);
	          });
	        }
	    },

	    onSubmitButton: function onSubmitButton(event) {
	      this._submitSource = event.currentTarget;
	    },
	    // internal
	    // _submit submits the form, this time without going through the validations.
	    // Care must be taken to "fake" the actual submit button being clicked.
	    _submit: function _submit(submitSource) {
	      if (false === this._trigger('submit')) return;
	      // Add submit button's data
	      if (submitSource) {
	        var $synthetic = this.$element.find('.parsley-synthetic-submit-button').prop('disabled', false);
	        if (0 === $synthetic.length) $synthetic = $('<input class="parsley-synthetic-submit-button" type="hidden">').appendTo(this.$element);
	        $synthetic.attr({
	          name: submitSource.getAttribute('name'),
	          value: submitSource.getAttribute('value')
	        });
	      }

	      this.$element.trigger(_extends($.Event('submit'), { parsley: true }));
	    },

	    // Performs validation on fields while triggering events.
	    // @returns `true` if all validations succeeds, `false`
	    // if a failure is immediately detected, or `null`
	    // if dependant on a promise.
	    // Consider using `whenValidate` instead.
	    validate: function validate(options) {
	      if (arguments.length >= 1 && !$.isPlainObject(options)) {
	        Utils.warnOnce('Calling validate on a parsley form without passing arguments as an object is deprecated.');

	        var _arguments = _slice.call(arguments);

	        var group = _arguments[0];
	        var force = _arguments[1];
	        var event = _arguments[2];

	        options = { group: group, force: force, event: event };
	      }
	      return Form__statusMapping[this.whenValidate(options).state()];
	    },

	    whenValidate: function whenValidate() {
	      var _Utils$all$done$fail$always,
	          _this6 = this;

	      var _ref7 = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];

	      var group = _ref7.group;
	      var force = _ref7.force;
	      var event = _ref7.event;

	      this.submitEvent = event;
	      if (event) {
	        this.submitEvent = _extends({}, event, { preventDefault: function preventDefault() {
	            Utils.warnOnce("Using `this.submitEvent.preventDefault()` is deprecated; instead, call `this.validationResult = false`");
	            _this6.validationResult = false;
	          } });
	      }
	      this.validationResult = true;

	      // fire validate event to eventually modify things before every validation
	      this._trigger('validate');

	      // Refresh form DOM options and form's fields that could have changed
	      this._refreshFields();

	      var promises = this._withoutReactualizingFormOptions(function () {
	        return $.map(_this6.fields, function (field) {
	          return field.whenValidate({ force: force, group: group });
	        });
	      });

	      return (_Utils$all$done$fail$always = Utils.all(promises).done(function () {
	        _this6._trigger('success');
	      }).fail(function () {
	        _this6.validationResult = false;
	        _this6.focus();
	        _this6._trigger('error');
	      }).always(function () {
	        _this6._trigger('validated');
	      })).pipe.apply(_Utils$all$done$fail$always, _toConsumableArray(this._pipeAccordingToValidationResult()));
	    },

	    // Iterate over refreshed fields, and stop on first failure.
	    // Returns `true` if all fields are valid, `false` if a failure is detected
	    // or `null` if the result depends on an unresolved promise.
	    // Prefer using `whenValid` instead.
	    isValid: function isValid(options) {
	      if (arguments.length >= 1 && !$.isPlainObject(options)) {
	        Utils.warnOnce('Calling isValid on a parsley form without passing arguments as an object is deprecated.');

	        var _arguments2 = _slice.call(arguments);

	        var group = _arguments2[0];
	        var force = _arguments2[1];

	        options = { group: group, force: force };
	      }
	      return Form__statusMapping[this.whenValid(options).state()];
	    },

	    // Iterate over refreshed fields and validate them.
	    // Returns a promise.
	    // A validation that immediately fails will interrupt the validations.
	    whenValid: function whenValid() {
	      var _this7 = this;

	      var _ref8 = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];

	      var group = _ref8.group;
	      var force = _ref8.force;

	      this._refreshFields();

	      var promises = this._withoutReactualizingFormOptions(function () {
	        return $.map(_this7.fields, function (field) {
	          return field.whenValid({ group: group, force: force });
	        });
	      });
	      return Utils.all(promises);
	    },

	    // Reset UI
	    reset: function reset() {
	      // Form case: emit a reset event for each field
	      for (var i = 0; i < this.fields.length; i++) this.fields[i].reset();

	      this._trigger('reset');
	    },

	    // Destroy Parsley instance (+ UI)
	    destroy: function destroy() {
	      // Field case: emit destroy event to clean UI and then destroy stored instance
	      this._destroyUI();

	      // Form case: destroy all its fields and then destroy stored instance
	      for (var i = 0; i < this.fields.length; i++) this.fields[i].destroy();

	      this.$element.removeData('Parsley');
	      this._trigger('destroy');
	    },

	    _refreshFields: function _refreshFields() {
	      return this.actualizeOptions()._bindFields();
	    },

	    _bindFields: function _bindFields() {
	      var _this8 = this;

	      var oldFields = this.fields;

	      this.fields = [];
	      this.fieldsMappedById = {};

	      this._withoutReactualizingFormOptions(function () {
	        _this8.$element.find(_this8.options.inputs).not(_this8.options.excluded).each(function (_, element) {
	          var fieldInstance = new window.Parsley.Factory(element, {}, _this8);

	          // Only add valid and not excluded `Field` and `FieldMultiple` children
	          if (('Field' === fieldInstance.__class__ || 'FieldMultiple' === fieldInstance.__class__) && true !== fieldInstance.options.excluded) {
	            var uniqueId = fieldInstance.__class__ + '-' + fieldInstance.__id__;
	            if ('undefined' === typeof _this8.fieldsMappedById[uniqueId]) {
	              _this8.fieldsMappedById[uniqueId] = fieldInstance;
	              _this8.fields.push(fieldInstance);
	            }
	          }
	        });

	        $.each(Utils.difference(oldFields, _this8.fields), function (_, field) {
	          field.reset();
	        });
	      });
	      return this;
	    },

	    // Internal only.
	    // Looping on a form's fields to do validation or similar
	    // will trigger reactualizing options on all of them, which
	    // in turn will reactualize the form's options.
	    // To avoid calling actualizeOptions so many times on the form
	    // for nothing, _withoutReactualizingFormOptions temporarily disables
	    // the method actualizeOptions on this form while `fn` is called.
	    _withoutReactualizingFormOptions: function _withoutReactualizingFormOptions(fn) {
	      var oldActualizeOptions = this.actualizeOptions;
	      this.actualizeOptions = function () {
	        return this;
	      };
	      var result = fn();
	      this.actualizeOptions = oldActualizeOptions;
	      return result;
	    },

	    // Internal only.
	    // Shortcut to trigger an event
	    // Returns true iff event is not interrupted and default not prevented.
	    _trigger: function _trigger(eventName) {
	      return this.trigger('form:' + eventName);
	    }

	  };

	  var Constraint = function Constraint(parsleyField, name, requirements, priority, isDomConstraint) {
	    var validatorSpec = window.Parsley._validatorRegistry.validators[name];
	    var validator = new Validator(validatorSpec);
	    priority = priority || parsleyField.options[name + 'Priority'] || validator.priority;
	    isDomConstraint = true === isDomConstraint;

	    _extends(this, {
	      validator: validator,
	      name: name,
	      requirements: requirements,
	      priority: priority,
	      isDomConstraint: isDomConstraint
	    });
	    this._parseRequirements(parsleyField.options);
	  };

	  var capitalize = function capitalize(str) {
	    var cap = str[0].toUpperCase();
	    return cap + str.slice(1);
	  };

	  Constraint.prototype = {
	    validate: function validate(value, instance) {
	      var _validator;

	      return (_validator = this.validator).validate.apply(_validator, [value].concat(_toConsumableArray(this.requirementList), [instance]));
	    },

	    _parseRequirements: function _parseRequirements(options) {
	      var _this9 = this;

	      this.requirementList = this.validator.parseRequirements(this.requirements, function (key) {
	        return options[_this9.name + capitalize(key)];
	      });
	    }
	  };

	  var Field = function Field(field, domOptions, options, parsleyFormInstance) {
	    this.__class__ = 'Field';

	    this.element = field;
	    this.$element = $(field);

	    // Set parent if we have one
	    if ('undefined' !== typeof parsleyFormInstance) {
	      this.parent = parsleyFormInstance;
	    }

	    this.options = options;
	    this.domOptions = domOptions;

	    // Initialize some properties
	    this.constraints = [];
	    this.constraintsByName = {};
	    this.validationResult = true;

	    // Bind constraints
	    this._bindConstraints();
	  };

	  var parsley_field__statusMapping = { pending: null, resolved: true, rejected: false };

	  Field.prototype = {
	    // # Public API
	    // Validate field and trigger some events for mainly `UI`
	    // @returns `true`, an array of the validators that failed, or
	    // `null` if validation is not finished. Prefer using whenValidate
	    validate: function validate(options) {
	      if (arguments.length >= 1 && !$.isPlainObject(options)) {
	        Utils.warnOnce('Calling validate on a parsley field without passing arguments as an object is deprecated.');
	        options = { options: options };
	      }
	      var promise = this.whenValidate(options);
	      if (!promise) // If excluded with `group` option
	        return true;
	      switch (promise.state()) {
	        case 'pending':
	          return null;
	        case 'resolved':
	          return true;
	        case 'rejected':
	          return this.validationResult;
	      }
	    },

	    // Validate field and trigger some events for mainly `UI`
	    // @returns a promise that succeeds only when all validations do
	    // or `undefined` if field is not in the given `group`.
	    whenValidate: function whenValidate() {
	      var _whenValid$always$done$fail$always,
	          _this10 = this;

	      var _ref9 = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];

	      var force = _ref9.force;
	      var group = _ref9.group;

	      // do not validate a field if not the same as given validation group
	      this.refreshConstraints();
	      if (group && !this._isInGroup(group)) return;

	      this.value = this.getValue();

	      // Field Validate event. `this.value` could be altered for custom needs
	      this._trigger('validate');

	      return (_whenValid$always$done$fail$always = this.whenValid({ force: force, value: this.value, _refreshed: true }).always(function () {
	        _this10._reflowUI();
	      }).done(function () {
	        _this10._trigger('success');
	      }).fail(function () {
	        _this10._trigger('error');
	      }).always(function () {
	        _this10._trigger('validated');
	      })).pipe.apply(_whenValid$always$done$fail$always, _toConsumableArray(this._pipeAccordingToValidationResult()));
	    },

	    hasConstraints: function hasConstraints() {
	      return 0 !== this.constraints.length;
	    },

	    // An empty optional field does not need validation
	    needsValidation: function needsValidation(value) {
	      if ('undefined' === typeof value) value = this.getValue();

	      // If a field is empty and not required, it is valid
	      // Except if `data-parsley-validate-if-empty` explicitely added, useful for some custom validators
	      if (!value.length && !this._isRequired() && 'undefined' === typeof this.options.validateIfEmpty) return false;

	      return true;
	    },

	    _isInGroup: function _isInGroup(group) {
	      if (Array.isArray(this.options.group)) return -1 !== $.inArray(group, this.options.group);
	      return this.options.group === group;
	    },

	    // Just validate field. Do not trigger any event.
	    // Returns `true` iff all constraints pass, `false` if there are failures,
	    // or `null` if the result can not be determined yet (depends on a promise)
	    // See also `whenValid`.
	    isValid: function isValid(options) {
	      if (arguments.length >= 1 && !$.isPlainObject(options)) {
	        Utils.warnOnce('Calling isValid on a parsley field without passing arguments as an object is deprecated.');

	        var _arguments3 = _slice.call(arguments);

	        var force = _arguments3[0];
	        var value = _arguments3[1];

	        options = { force: force, value: value };
	      }
	      var promise = this.whenValid(options);
	      if (!promise) // Excluded via `group`
	        return true;
	      return parsley_field__statusMapping[promise.state()];
	    },

	    // Just validate field. Do not trigger any event.
	    // @returns a promise that succeeds only when all validations do
	    // or `undefined` if the field is not in the given `group`.
	    // The argument `force` will force validation of empty fields.
	    // If a `value` is given, it will be validated instead of the value of the input.
	    whenValid: function whenValid() {
	      var _this11 = this;

	      var _ref10 = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];

	      var _ref10$force = _ref10.force;
	      var force = _ref10$force === undefined ? false : _ref10$force;
	      var value = _ref10.value;
	      var group = _ref10.group;
	      var _refreshed = _ref10._refreshed;

	      // Recompute options and rebind constraints to have latest changes
	      if (!_refreshed) this.refreshConstraints();
	      // do not validate a field if not the same as given validation group
	      if (group && !this._isInGroup(group)) return;

	      this.validationResult = true;

	      // A field without constraint is valid
	      if (!this.hasConstraints()) return $.when();

	      // Value could be passed as argument, needed to add more power to 'field:validate'
	      if ('undefined' === typeof value || null === value) value = this.getValue();

	      if (!this.needsValidation(value) && true !== force) return $.when();

	      var groupedConstraints = this._getGroupedConstraints();
	      var promises = [];
	      $.each(groupedConstraints, function (_, constraints) {
	        // Process one group of constraints at a time, we validate the constraints
	        // and combine the promises together.
	        var promise = Utils.all($.map(constraints, function (constraint) {
	          return _this11._validateConstraint(value, constraint);
	        }));
	        promises.push(promise);
	        if (promise.state() === 'rejected') return false; // Interrupt processing if a group has already failed
	      });
	      return Utils.all(promises);
	    },

	    // @returns a promise
	    _validateConstraint: function _validateConstraint(value, constraint) {
	      var _this12 = this;

	      var result = constraint.validate(value, this);
	      // Map false to a failed promise
	      if (false === result) result = $.Deferred().reject();
	      // Make sure we return a promise and that we record failures
	      return Utils.all([result]).fail(function (errorMessage) {
	        if (!(_this12.validationResult instanceof Array)) _this12.validationResult = [];
	        _this12.validationResult.push({
	          assert: constraint,
	          errorMessage: 'string' === typeof errorMessage && errorMessage
	        });
	      });
	    },

	    // @returns Parsley field computed value that could be overrided or configured in DOM
	    getValue: function getValue() {
	      var value;

	      // Value could be overriden in DOM or with explicit options
	      if ('function' === typeof this.options.value) value = this.options.value(this);else if ('undefined' !== typeof this.options.value) value = this.options.value;else value = this.$element.val();

	      // Handle wrong DOM or configurations
	      if ('undefined' === typeof value || null === value) return '';

	      return this._handleWhitespace(value);
	    },

	    // Reset UI
	    reset: function reset() {
	      this._resetUI();
	      return this._trigger('reset');
	    },

	    // Destroy Parsley instance (+ UI)
	    destroy: function destroy() {
	      // Field case: emit destroy event to clean UI and then destroy stored instance
	      this._destroyUI();
	      this.$element.removeData('Parsley');
	      this.$element.removeData('FieldMultiple');
	      this._trigger('destroy');
	    },

	    // Actualize options that could have change since previous validation
	    // Re-bind accordingly constraints (could be some new, removed or updated)
	    refreshConstraints: function refreshConstraints() {
	      return this.actualizeOptions()._bindConstraints();
	    },

	    /**
	    * Add a new constraint to a field
	    *
	    * @param {String}   name
	    * @param {Mixed}    requirements      optional
	    * @param {Number}   priority          optional
	    * @param {Boolean}  isDomConstraint   optional
	    */
	    addConstraint: function addConstraint(name, requirements, priority, isDomConstraint) {

	      if (window.Parsley._validatorRegistry.validators[name]) {
	        var constraint = new Constraint(this, name, requirements, priority, isDomConstraint);

	        // if constraint already exist, delete it and push new version
	        if ('undefined' !== this.constraintsByName[constraint.name]) this.removeConstraint(constraint.name);

	        this.constraints.push(constraint);
	        this.constraintsByName[constraint.name] = constraint;
	      }

	      return this;
	    },

	    // Remove a constraint
	    removeConstraint: function removeConstraint(name) {
	      for (var i = 0; i < this.constraints.length; i++) if (name === this.constraints[i].name) {
	        this.constraints.splice(i, 1);
	        break;
	      }
	      delete this.constraintsByName[name];
	      return this;
	    },

	    // Update a constraint (Remove + re-add)
	    updateConstraint: function updateConstraint(name, parameters, priority) {
	      return this.removeConstraint(name).addConstraint(name, parameters, priority);
	    },

	    // # Internals

	    // Internal only.
	    // Bind constraints from config + options + DOM
	    _bindConstraints: function _bindConstraints() {
	      var constraints = [];
	      var constraintsByName = {};

	      // clean all existing DOM constraints to only keep javascript user constraints
	      for (var i = 0; i < this.constraints.length; i++) if (false === this.constraints[i].isDomConstraint) {
	        constraints.push(this.constraints[i]);
	        constraintsByName[this.constraints[i].name] = this.constraints[i];
	      }

	      this.constraints = constraints;
	      this.constraintsByName = constraintsByName;

	      // then re-add Parsley DOM-API constraints
	      for (var name in this.options) this.addConstraint(name, this.options[name], undefined, true);

	      // finally, bind special HTML5 constraints
	      return this._bindHtml5Constraints();
	    },

	    // Internal only.
	    // Bind specific HTML5 constraints to be HTML5 compliant
	    _bindHtml5Constraints: function _bindHtml5Constraints() {
	      // html5 required
	      if (null !== this.element.getAttribute('required')) this.addConstraint('required', true, undefined, true);

	      // html5 pattern
	      if (null !== this.element.getAttribute('pattern')) this.addConstraint('pattern', this.element.getAttribute('pattern'), undefined, true);

	      // range
	      var min = this.element.getAttribute('min');
	      var max = this.element.getAttribute('max');
	      if (null !== min && null !== max) this.addConstraint('range', [min, max], undefined, true);

	      // HTML5 min
	      else if (null !== min) this.addConstraint('min', min, undefined, true);

	        // HTML5 max
	        else if (null !== max) this.addConstraint('max', max, undefined, true);

	      // length
	      if (null !== this.element.getAttribute('minlength') && null !== this.element.getAttribute('maxlength')) this.addConstraint('length', [this.element.getAttribute('minlength'), this.element.getAttribute('maxlength')], undefined, true);

	      // HTML5 minlength
	      else if (null !== this.element.getAttribute('minlength')) this.addConstraint('minlength', this.element.getAttribute('minlength'), undefined, true);

	        // HTML5 maxlength
	        else if (null !== this.element.getAttribute('maxlength')) this.addConstraint('maxlength', this.element.getAttribute('maxlength'), undefined, true);

	      // html5 types
	      var type = this.element.type;

	      // Small special case here for HTML5 number: integer validator if step attribute is undefined or an integer value, number otherwise
	      if ('number' === type) {
	        return this.addConstraint('type', ['number', {
	          step: this.element.getAttribute('step') || '1',
	          base: min || this.element.getAttribute('value')
	        }], undefined, true);
	        // Regular other HTML5 supported types
	      } else if (/^(email|url|range|date)$/i.test(type)) {
	          return this.addConstraint('type', type, undefined, true);
	        }
	      return this;
	    },

	    // Internal only.
	    // Field is required if have required constraint without `false` value
	    _isRequired: function _isRequired() {
	      if ('undefined' === typeof this.constraintsByName.required) return false;

	      return false !== this.constraintsByName.required.requirements;
	    },

	    // Internal only.
	    // Shortcut to trigger an event
	    _trigger: function _trigger(eventName) {
	      return this.trigger('field:' + eventName);
	    },

	    // Internal only
	    // Handles whitespace in a value
	    // Use `data-parsley-whitespace="squish"` to auto squish input value
	    // Use `data-parsley-whitespace="trim"` to auto trim input value
	    _handleWhitespace: function _handleWhitespace(value) {
	      if (true === this.options.trimValue) Utils.warnOnce('data-parsley-trim-value="true" is deprecated, please use data-parsley-whitespace="trim"');

	      if ('squish' === this.options.whitespace) value = value.replace(/\s{2,}/g, ' ');

	      if ('trim' === this.options.whitespace || 'squish' === this.options.whitespace || true === this.options.trimValue) value = Utils.trimString(value);

	      return value;
	    },

	    _isDateInput: function _isDateInput() {
	      var c = this.constraintsByName.type;
	      return c && c.requirements === 'date';
	    },

	    // Internal only.
	    // Returns the constraints, grouped by descending priority.
	    // The result is thus an array of arrays of constraints.
	    _getGroupedConstraints: function _getGroupedConstraints() {
	      if (false === this.options.priorityEnabled) return [this.constraints];

	      var groupedConstraints = [];
	      var index = {};

	      // Create array unique of priorities
	      for (var i = 0; i < this.constraints.length; i++) {
	        var p = this.constraints[i].priority;
	        if (!index[p]) groupedConstraints.push(index[p] = []);
	        index[p].push(this.constraints[i]);
	      }
	      // Sort them by priority DESC
	      groupedConstraints.sort(function (a, b) {
	        return b[0].priority - a[0].priority;
	      });

	      return groupedConstraints;
	    }

	  };

	  var parsley_field = Field;

	  var Multiple = function Multiple() {
	    this.__class__ = 'FieldMultiple';
	  };

	  Multiple.prototype = {
	    // Add new `$element` sibling for multiple field
	    addElement: function addElement($element) {
	      this.$elements.push($element);

	      return this;
	    },

	    // See `Field.refreshConstraints()`
	    refreshConstraints: function refreshConstraints() {
	      var fieldConstraints;

	      this.constraints = [];

	      // Select multiple special treatment
	      if (this.element.nodeName === 'SELECT') {
	        this.actualizeOptions()._bindConstraints();

	        return this;
	      }

	      // Gather all constraints for each input in the multiple group
	      for (var i = 0; i < this.$elements.length; i++) {

	        // Check if element have not been dynamically removed since last binding
	        if (!$('html').has(this.$elements[i]).length) {
	          this.$elements.splice(i, 1);
	          continue;
	        }

	        fieldConstraints = this.$elements[i].data('FieldMultiple').refreshConstraints().constraints;

	        for (var j = 0; j < fieldConstraints.length; j++) this.addConstraint(fieldConstraints[j].name, fieldConstraints[j].requirements, fieldConstraints[j].priority, fieldConstraints[j].isDomConstraint);
	      }

	      return this;
	    },

	    // See `Field.getValue()`
	    getValue: function getValue() {
	      // Value could be overriden in DOM
	      if ('function' === typeof this.options.value) return this.options.value(this);else if ('undefined' !== typeof this.options.value) return this.options.value;

	      // Radio input case
	      if (this.element.nodeName === 'INPUT') {
	        if (this.element.type === 'radio') return this._findRelated().filter(':checked').val() || '';

	        // checkbox input case
	        if (this.element.type === 'checkbox') {
	          var values = [];

	          this._findRelated().filter(':checked').each(function () {
	            values.push($(this).val());
	          });

	          return values;
	        }
	      }

	      // Select multiple case
	      if (this.element.nodeName === 'SELECT' && null === this.$element.val()) return [];

	      // Default case that should never happen
	      return this.$element.val();
	    },

	    _init: function _init() {
	      this.$elements = [this.$element];

	      return this;
	    }
	  };

	  var Factory = function Factory(element, options, parsleyFormInstance) {
	    this.element = element;
	    this.$element = $(element);

	    // If the element has already been bound, returns its saved Parsley instance
	    var savedparsleyFormInstance = this.$element.data('Parsley');
	    if (savedparsleyFormInstance) {

	      // If the saved instance has been bound without a Form parent and there is one given in this call, add it
	      if ('undefined' !== typeof parsleyFormInstance && savedparsleyFormInstance.parent === window.Parsley) {
	        savedparsleyFormInstance.parent = parsleyFormInstance;
	        savedparsleyFormInstance._resetOptions(savedparsleyFormInstance.options);
	      }

	      if ('object' === typeof options) {
	        _extends(savedparsleyFormInstance.options, options);
	      }

	      return savedparsleyFormInstance;
	    }

	    // Parsley must be instantiated with a DOM element or jQuery $element
	    if (!this.$element.length) throw new Error('You must bind Parsley on an existing element.');

	    if ('undefined' !== typeof parsleyFormInstance && 'Form' !== parsleyFormInstance.__class__) throw new Error('Parent instance must be a Form instance');

	    this.parent = parsleyFormInstance || window.Parsley;
	    return this.init(options);
	  };

	  Factory.prototype = {
	    init: function init(options) {
	      this.__class__ = 'Parsley';
	      this.__version__ = '2.7.2';
	      this.__id__ = Utils.generateID();

	      // Pre-compute options
	      this._resetOptions(options);

	      // A Form instance is obviously a `<form>` element but also every node that is not an input and has the `data-parsley-validate` attribute
	      if (this.element.nodeName === 'FORM' || Utils.checkAttr(this.element, this.options.namespace, 'validate') && !this.$element.is(this.options.inputs)) return this.bind('parsleyForm');

	      // Every other element is bound as a `Field` or `FieldMultiple`
	      return this.isMultiple() ? this.handleMultiple() : this.bind('parsleyField');
	    },

	    isMultiple: function isMultiple() {
	      return this.element.type === 'radio' || this.element.type === 'checkbox' || this.element.nodeName === 'SELECT' && null !== this.element.getAttribute('multiple');
	    },

	    // Multiples fields are a real nightmare :(
	    // Maybe some refactoring would be appreciated here...
	    handleMultiple: function handleMultiple() {
	      var _this13 = this;

	      var name;
	      var multiple;
	      var parsleyMultipleInstance;

	      // Handle multiple name
	      this.options.multiple = this.options.multiple || (name = this.element.getAttribute('name')) || this.element.getAttribute('id');

	      // Special select multiple input
	      if (this.element.nodeName === 'SELECT' && null !== this.element.getAttribute('multiple')) {
	        this.options.multiple = this.options.multiple || this.__id__;
	        return this.bind('parsleyFieldMultiple');

	        // Else for radio / checkboxes, we need a `name` or `data-parsley-multiple` to properly bind it
	      } else if (!this.options.multiple) {
	          Utils.warn('To be bound by Parsley, a radio, a checkbox and a multiple select input must have either a name or a multiple option.', this.$element);
	          return this;
	        }

	      // Remove special chars
	      this.options.multiple = this.options.multiple.replace(/(:|\.|\[|\]|\{|\}|\$)/g, '');

	      // Add proper `data-parsley-multiple` to siblings if we have a valid multiple name
	      if (name) {
	        $('input[name="' + name + '"]').each(function (i, input) {
	          if (input.type === 'radio' || input.type === 'checkbox') input.setAttribute(_this13.options.namespace + 'multiple', _this13.options.multiple);
	        });
	      }

	      // Check here if we don't already have a related multiple instance saved
	      var $previouslyRelated = this._findRelated();
	      for (var i = 0; i < $previouslyRelated.length; i++) {
	        parsleyMultipleInstance = $($previouslyRelated.get(i)).data('Parsley');
	        if ('undefined' !== typeof parsleyMultipleInstance) {

	          if (!this.$element.data('FieldMultiple')) {
	            parsleyMultipleInstance.addElement(this.$element);
	          }

	          break;
	        }
	      }

	      // Create a secret Field instance for every multiple field. It will be stored in `data('FieldMultiple')`
	      // And will be useful later to access classic `Field` stuff while being in a `FieldMultiple` instance
	      this.bind('parsleyField', true);

	      return parsleyMultipleInstance || this.bind('parsleyFieldMultiple');
	    },

	    // Return proper `Form`, `Field` or `FieldMultiple`
	    bind: function bind(type, doNotStore) {
	      var parsleyInstance;

	      switch (type) {
	        case 'parsleyForm':
	          parsleyInstance = $.extend(new Form(this.element, this.domOptions, this.options), new Base(), window.ParsleyExtend)._bindFields();
	          break;
	        case 'parsleyField':
	          parsleyInstance = $.extend(new parsley_field(this.element, this.domOptions, this.options, this.parent), new Base(), window.ParsleyExtend);
	          break;
	        case 'parsleyFieldMultiple':
	          parsleyInstance = $.extend(new parsley_field(this.element, this.domOptions, this.options, this.parent), new Multiple(), new Base(), window.ParsleyExtend)._init();
	          break;
	        default:
	          throw new Error(type + 'is not a supported Parsley type');
	      }

	      if (this.options.multiple) Utils.setAttr(this.element, this.options.namespace, 'multiple', this.options.multiple);

	      if ('undefined' !== typeof doNotStore) {
	        this.$element.data('FieldMultiple', parsleyInstance);

	        return parsleyInstance;
	      }

	      // Store the freshly bound instance in a DOM element for later access using jQuery `data()`
	      this.$element.data('Parsley', parsleyInstance);

	      // Tell the world we have a new Form or Field instance!
	      parsleyInstance._actualizeTriggers();
	      parsleyInstance._trigger('init');

	      return parsleyInstance;
	    }
	  };

	  var vernums = $.fn.jquery.split('.');
	  if (parseInt(vernums[0]) <= 1 && parseInt(vernums[1]) < 8) {
	    throw "The loaded version of jQuery is too old. Please upgrade to 1.8.x or better.";
	  }
	  if (!vernums.forEach) {
	    Utils.warn('Parsley requires ES5 to run properly. Please include https://github.com/es-shims/es5-shim');
	  }
	  // Inherit `on`, `off` & `trigger` to Parsley:
	  var Parsley = _extends(new Base(), {
	    element: document,
	    $element: $(document),
	    actualizeOptions: null,
	    _resetOptions: null,
	    Factory: Factory,
	    version: '2.7.2'
	  });

	  // Supplement Field and Form with Base
	  // This way, the constructors will have access to those methods
	  _extends(parsley_field.prototype, UI.Field, Base.prototype);
	  _extends(Form.prototype, UI.Form, Base.prototype);
	  // Inherit actualizeOptions and _resetOptions:
	  _extends(Factory.prototype, Base.prototype);

	  // ### jQuery API
	  // `$('.elem').parsley(options)` or `$('.elem').psly(options)`
	  $.fn.parsley = $.fn.psly = function (options) {
	    if (this.length > 1) {
	      var instances = [];

	      this.each(function () {
	        instances.push($(this).parsley(options));
	      });

	      return instances;
	    }

	    // Return undefined if applied to non existing DOM element
	    if (!$(this).length) {
	      Utils.warn('You must bind Parsley on an existing element.');

	      return;
	    }

	    return new Factory(this[0], options);
	  };

	  // ### Field and Form extension
	  // Ensure the extension is now defined if it wasn't previously
	  if ('undefined' === typeof window.ParsleyExtend) window.ParsleyExtend = {};

	  // ### Parsley config
	  // Inherit from ParsleyDefault, and copy over any existing values
	  Parsley.options = _extends(Utils.objectCreate(Defaults), window.ParsleyConfig);
	  window.ParsleyConfig = Parsley.options; // Old way of accessing global options

	  // ### Globals
	  window.Parsley = window.psly = Parsley;
	  Parsley.Utils = Utils;
	  window.ParsleyUtils = {};
	  $.each(Utils, function (key, value) {
	    if ('function' === typeof value) {
	      window.ParsleyUtils[key] = function () {
	        Utils.warnOnce('Accessing `window.ParsleyUtils` is deprecated. Use `window.Parsley.Utils` instead.');
	        return Utils[key].apply(Utils, arguments);
	      };
	    }
	  });

	  // ### Define methods that forward to the registry, and deprecate all access except through window.Parsley
	  var registry = window.Parsley._validatorRegistry = new ValidatorRegistry(window.ParsleyConfig.validators, window.ParsleyConfig.i18n);
	  window.ParsleyValidator = {};
	  $.each('setLocale addCatalog addMessage addMessages getErrorMessage formatMessage addValidator updateValidator removeValidator'.split(' '), function (i, method) {
	    window.Parsley[method] = function () {
	      return registry[method].apply(registry, arguments);
	    };
	    window.ParsleyValidator[method] = function () {
	      var _window$Parsley;

	      Utils.warnOnce('Accessing the method \'' + method + '\' through Validator is deprecated. Simply call \'window.Parsley.' + method + '(...)\'');
	      return (_window$Parsley = window.Parsley)[method].apply(_window$Parsley, arguments);
	    };
	  });

	  // ### UI
	  // Deprecated global object
	  window.Parsley.UI = UI;
	  window.ParsleyUI = {
	    removeError: function removeError(instance, name, doNotUpdateClass) {
	      var updateClass = true !== doNotUpdateClass;
	      Utils.warnOnce('Accessing UI is deprecated. Call \'removeError\' on the instance directly. Please comment in issue 1073 as to your need to call this method.');
	      return instance.removeError(name, { updateClass: updateClass });
	    },
	    getErrorsMessages: function getErrorsMessages(instance) {
	      Utils.warnOnce('Accessing UI is deprecated. Call \'getErrorsMessages\' on the instance directly.');
	      return instance.getErrorsMessages();
	    }
	  };
	  $.each('addError updateError'.split(' '), function (i, method) {
	    window.ParsleyUI[method] = function (instance, name, message, assert, doNotUpdateClass) {
	      var updateClass = true !== doNotUpdateClass;
	      Utils.warnOnce('Accessing UI is deprecated. Call \'' + method + '\' on the instance directly. Please comment in issue 1073 as to your need to call this method.');
	      return instance[method](name, { message: message, assert: assert, updateClass: updateClass });
	    };
	  });

	  // ### PARSLEY auto-binding
	  // Prevent it by setting `ParsleyConfig.autoBind` to `false`
	  if (false !== window.ParsleyConfig.autoBind) {
	    $(function () {
	      // Works only on `data-parsley-validate`.
	      if ($('[data-parsley-validate]').length) $('[data-parsley-validate]').parsley();
	    });
	  }

	  var o = $({});
	  var deprecated = function deprecated() {
	    Utils.warnOnce("Parsley's pubsub module is deprecated; use the 'on' and 'off' methods on parsley instances or window.Parsley");
	  };

	  // Returns an event handler that calls `fn` with the arguments it expects
	  function adapt(fn, context) {
	    // Store to allow unbinding
	    if (!fn.parsleyAdaptedCallback) {
	      fn.parsleyAdaptedCallback = function () {
	        var args = Array.prototype.slice.call(arguments, 0);
	        args.unshift(this);
	        fn.apply(context || o, args);
	      };
	    }
	    return fn.parsleyAdaptedCallback;
	  }

	  var eventPrefix = 'parsley:';
	  // Converts 'parsley:form:validate' into 'form:validate'
	  function eventName(name) {
	    if (name.lastIndexOf(eventPrefix, 0) === 0) return name.substr(eventPrefix.length);
	    return name;
	  }

	  // $.listen is deprecated. Use Parsley.on instead.
	  $.listen = function (name, callback) {
	    var context;
	    deprecated();
	    if ('object' === typeof arguments[1] && 'function' === typeof arguments[2]) {
	      context = arguments[1];
	      callback = arguments[2];
	    }

	    if ('function' !== typeof callback) throw new Error('Wrong parameters');

	    window.Parsley.on(eventName(name), adapt(callback, context));
	  };

	  $.listenTo = function (instance, name, fn) {
	    deprecated();
	    if (!(instance instanceof parsley_field) && !(instance instanceof Form)) throw new Error('Must give Parsley instance');

	    if ('string' !== typeof name || 'function' !== typeof fn) throw new Error('Wrong parameters');

	    instance.on(eventName(name), adapt(fn));
	  };

	  $.unsubscribe = function (name, fn) {
	    deprecated();
	    if ('string' !== typeof name || 'function' !== typeof fn) throw new Error('Wrong arguments');
	    window.Parsley.off(eventName(name), fn.parsleyAdaptedCallback);
	  };

	  $.unsubscribeTo = function (instance, name) {
	    deprecated();
	    if (!(instance instanceof parsley_field) && !(instance instanceof Form)) throw new Error('Must give Parsley instance');
	    instance.off(eventName(name));
	  };

	  $.unsubscribeAll = function (name) {
	    deprecated();
	    window.Parsley.off(eventName(name));
	    $('form,input,textarea,select').each(function () {
	      var instance = $(this).data('Parsley');
	      if (instance) {
	        instance.off(eventName(name));
	      }
	    });
	  };

	  // $.emit is deprecated. Use jQuery events instead.
	  $.emit = function (name, instance) {
	    var _instance;

	    deprecated();
	    var instanceGiven = instance instanceof parsley_field || instance instanceof Form;
	    var args = Array.prototype.slice.call(arguments, instanceGiven ? 2 : 1);
	    args.unshift(eventName(name));
	    if (!instanceGiven) {
	      instance = window.Parsley;
	    }
	    (_instance = instance).trigger.apply(_instance, _toConsumableArray(args));
	  };

	  var pubsub = {};

	  $.extend(true, Parsley, {
	    asyncValidators: {
	      'default': {
	        fn: function fn(xhr) {
	          // By default, only status 2xx are deemed successful.
	          // Note: we use status instead of state() because responses with status 200
	          // but invalid messages (e.g. an empty body for content type set to JSON) will
	          // result in state() === 'rejected'.
	          return xhr.status >= 200 && xhr.status < 300;
	        },
	        url: false
	      },
	      reverse: {
	        fn: function fn(xhr) {
	          // If reverse option is set, a failing ajax request is considered successful
	          return xhr.status < 200 || xhr.status >= 300;
	        },
	        url: false
	      }
	    },

	    addAsyncValidator: function addAsyncValidator(name, fn, url, options) {
	      Parsley.asyncValidators[name] = {
	        fn: fn,
	        url: url || false,
	        options: options || {}
	      };

	      return this;
	    }

	  });

	  Parsley.addValidator('remote', {
	    requirementType: {
	      '': 'string',
	      'validator': 'string',
	      'reverse': 'boolean',
	      'options': 'object'
	    },

	    validateString: function validateString(value, url, options, instance) {
	      var data = {};
	      var ajaxOptions;
	      var csr;
	      var validator = options.validator || (true === options.reverse ? 'reverse' : 'default');

	      if ('undefined' === typeof Parsley.asyncValidators[validator]) throw new Error('Calling an undefined async validator: `' + validator + '`');

	      url = Parsley.asyncValidators[validator].url || url;

	      // Fill current value
	      if (url.indexOf('{value}') > -1) {
	        url = url.replace('{value}', encodeURIComponent(value));
	      } else {
	        data[instance.element.getAttribute('name') || instance.element.getAttribute('id')] = value;
	      }

	      // Merge options passed in from the function with the ones in the attribute
	      var remoteOptions = $.extend(true, options.options || {}, Parsley.asyncValidators[validator].options);

	      // All `$.ajax(options)` could be overridden or extended directly from DOM in `data-parsley-remote-options`
	      ajaxOptions = $.extend(true, {}, {
	        url: url,
	        data: data,
	        type: 'GET'
	      }, remoteOptions);

	      // Generate store key based on ajax options
	      instance.trigger('field:ajaxoptions', instance, ajaxOptions);

	      csr = $.param(ajaxOptions);

	      // Initialise querry cache
	      if ('undefined' === typeof Parsley._remoteCache) Parsley._remoteCache = {};

	      // Try to retrieve stored xhr
	      var xhr = Parsley._remoteCache[csr] = Parsley._remoteCache[csr] || $.ajax(ajaxOptions);

	      var handleXhr = function handleXhr() {
	        var result = Parsley.asyncValidators[validator].fn.call(instance, xhr, url, options);
	        if (!result) // Map falsy results to rejected promise
	          result = $.Deferred().reject();
	        return $.when(result);
	      };

	      return xhr.then(handleXhr, handleXhr);
	    },

	    priority: -1
	  });

	  Parsley.on('form:submit', function () {
	    Parsley._remoteCache = {};
	  });

	  Base.prototype.addAsyncValidator = function () {
	    Utils.warnOnce('Accessing the method `addAsyncValidator` through an instance is deprecated. Simply call `Parsley.addAsyncValidator(...)`');
	    return Parsley.addAsyncValidator.apply(Parsley, arguments);
	  };

	  // This is included with the Parsley library itself,
	  // thus there is no use in adding it to your project.
	  Parsley.addMessages('en', {
	    defaultMessage: "This value seems to be invalid.",
	    type: {
	      email: "This value should be a valid email.",
	      url: "This value should be a valid url.",
	      number: "This value should be a valid number.",
	      integer: "This value should be a valid integer.",
	      digits: "This value should be digits.",
	      alphanum: "This value should be alphanumeric."
	    },
	    notblank: "This value should not be blank.",
	    required: "This value is required.",
	    pattern: "This value seems to be invalid.",
	    min: "This value should be greater than or equal to %s.",
	    max: "This value should be lower than or equal to %s.",
	    range: "This value should be between %s and %s.",
	    minlength: "This value is too short. It should have %s characters or more.",
	    maxlength: "This value is too long. It should have %s characters or fewer.",
	    length: "This value length is invalid. It should be between %s and %s characters long.",
	    mincheck: "You must select at least %s choices.",
	    maxcheck: "You must select %s choices or fewer.",
	    check: "You must select between %s and %s choices.",
	    equalto: "This value should be the same."
	  });

	  Parsley.setLocale('en');

	  /**
	   * inputevent - Alleviate browser bugs for input events
	   * https://github.com/marcandre/inputevent
	   * @version v0.0.3 - (built Thu, Apr 14th 2016, 5:58 pm)
	   * @author Marc-Andre Lafortune <github@marc-andre.ca>
	   * @license MIT
	   */

	  function InputEvent() {
	    var _this14 = this;

	    var globals = window || global;

	    // Slightly odd way construct our object. This way methods are force bound.
	    // Used to test for duplicate library.
	    _extends(this, {

	      // For browsers that do not support isTrusted, assumes event is native.
	      isNativeEvent: function isNativeEvent(evt) {
	        return evt.originalEvent && evt.originalEvent.isTrusted !== false;
	      },

	      fakeInputEvent: function fakeInputEvent(evt) {
	        if (_this14.isNativeEvent(evt)) {
	          $(evt.target).trigger('input');
	        }
	      },

	      misbehaves: function misbehaves(evt) {
	        if (_this14.isNativeEvent(evt)) {
	          _this14.behavesOk(evt);
	          $(document).on('change.inputevent', evt.data.selector, _this14.fakeInputEvent);
	          _this14.fakeInputEvent(evt);
	        }
	      },

	      behavesOk: function behavesOk(evt) {
	        if (_this14.isNativeEvent(evt)) {
	          $(document) // Simply unbinds the testing handler
	          .off('input.inputevent', evt.data.selector, _this14.behavesOk).off('change.inputevent', evt.data.selector, _this14.misbehaves);
	        }
	      },

	      // Bind the testing handlers
	      install: function install() {
	        if (globals.inputEventPatched) {
	          return;
	        }
	        globals.inputEventPatched = '0.0.3';
	        var _arr = ['select', 'input[type="checkbox"]', 'input[type="radio"]', 'input[type="file"]'];
	        for (var _i = 0; _i < _arr.length; _i++) {
	          var selector = _arr[_i];
	          $(document).on('input.inputevent', selector, { selector: selector }, _this14.behavesOk).on('change.inputevent', selector, { selector: selector }, _this14.misbehaves);
	        }
	      },

	      uninstall: function uninstall() {
	        delete globals.inputEventPatched;
	        $(document).off('.inputevent');
	      }

	    });
	  };

	  var inputevent = new InputEvent();

	  inputevent.install();

	  var parsley = Parsley;

	  return parsley;
	});
	//# sourceMappingURL=parsley.js.map

	/* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }())))

/***/ }
/******/ ]);